• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::error::Result;
2 use crate::measurement::ValueFormatter;
3 use crate::report::{BenchmarkId, MeasurementData, Report, ReportContext};
4 use crate::Throughput;
5 use csv::Writer;
6 use std::io::Write;
7 use std::path::Path;
8 
9 #[derive(Serialize)]
10 struct CsvRow<'a> {
11     group: &'a str,
12     function: Option<&'a str>,
13     value: Option<&'a str>,
14     throughput_num: Option<&'a str>,
15     throughput_type: Option<&'a str>,
16     sample_measured_value: f64,
17     unit: &'static str,
18     iteration_count: u64,
19 }
20 
21 struct CsvReportWriter<W: Write> {
22     writer: Writer<W>,
23 }
24 impl<W: Write> CsvReportWriter<W> {
write_data( &mut self, id: &BenchmarkId, data: &MeasurementData<'_>, formatter: &dyn ValueFormatter, ) -> Result<()>25     fn write_data(
26         &mut self,
27         id: &BenchmarkId,
28         data: &MeasurementData<'_>,
29         formatter: &dyn ValueFormatter,
30     ) -> Result<()> {
31         let mut data_scaled: Vec<f64> = data.sample_times().as_ref().into();
32         let unit = formatter.scale_for_machines(&mut data_scaled);
33         let group = id.group_id.as_str();
34         let function = id.function_id.as_deref();
35         let value = id.value_str.as_deref();
36         let (throughput_num, throughput_type) = match id.throughput {
37             Some(Throughput::Bytes(bytes)) => (Some(format!("{}", bytes)), Some("bytes")),
38             Some(Throughput::Elements(elems)) => (Some(format!("{}", elems)), Some("elements")),
39             None => (None, None),
40         };
41         let throughput_num = throughput_num.as_deref();
42 
43         for (count, measured_value) in data.iter_counts().iter().zip(data_scaled.into_iter()) {
44             let row = CsvRow {
45                 group,
46                 function,
47                 value,
48                 throughput_num,
49                 throughput_type,
50                 sample_measured_value: measured_value,
51                 unit,
52                 iteration_count: (*count) as u64,
53             };
54             self.writer.serialize(row)?;
55         }
56         Ok(())
57     }
58 }
59 
60 pub struct FileCsvReport;
61 impl FileCsvReport {
write_file( &self, path: &Path, id: &BenchmarkId, measurements: &MeasurementData<'_>, formatter: &dyn ValueFormatter, ) -> Result<()>62     fn write_file(
63         &self,
64         path: &Path,
65         id: &BenchmarkId,
66         measurements: &MeasurementData<'_>,
67         formatter: &dyn ValueFormatter,
68     ) -> Result<()> {
69         let writer = Writer::from_path(path)?;
70         let mut writer = CsvReportWriter { writer };
71         writer.write_data(id, measurements, formatter)?;
72         Ok(())
73     }
74 }
75 
76 impl Report for FileCsvReport {
measurement_complete( &self, id: &BenchmarkId, context: &ReportContext, measurements: &MeasurementData<'_>, formatter: &dyn ValueFormatter, )77     fn measurement_complete(
78         &self,
79         id: &BenchmarkId,
80         context: &ReportContext,
81         measurements: &MeasurementData<'_>,
82         formatter: &dyn ValueFormatter,
83     ) {
84         let mut path = context.output_directory.clone();
85         path.push(id.as_directory_name());
86         path.push("new");
87         path.push("raw.csv");
88         log_if_err!(self.write_file(&path, id, measurements, formatter));
89     }
90 }
91