diff options
Diffstat (limited to 'src/csv_report.rs')
-rwxr-xr-x | src/csv_report.rs | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/src/csv_report.rs b/src/csv_report.rs new file mode 100755 index 0000000..f30b817 --- /dev/null +++ b/src/csv_report.rs @@ -0,0 +1,90 @@ +use crate::error::Result; +use crate::measurement::ValueFormatter; +use crate::report::{BenchmarkId, MeasurementData, Report, ReportContext}; +use crate::Throughput; +use csv::Writer; +use std::io::Write; +use std::path::Path; + +#[derive(Serialize)] +struct CsvRow<'a> { + group: &'a str, + function: Option<&'a str>, + value: Option<&'a str>, + throughput_num: Option<&'a str>, + throughput_type: Option<&'a str>, + sample_measured_value: f64, + unit: &'static str, + iteration_count: u64, +} + +struct CsvReportWriter<W: Write> { + writer: Writer<W>, +} +impl<W: Write> CsvReportWriter<W> { + fn write_data( + &mut self, + id: &BenchmarkId, + data: &MeasurementData<'_>, + formatter: &dyn ValueFormatter, + ) -> Result<()> { + let mut data_scaled: Vec<f64> = data.sample_times().as_ref().into(); + let unit = formatter.scale_for_machines(&mut data_scaled); + let group = id.group_id.as_str(); + let function = id.function_id.as_ref().map(String::as_str); + let value = id.value_str.as_ref().map(String::as_str); + let (throughput_num, throughput_type) = match id.throughput { + Some(Throughput::Bytes(bytes)) => (Some(format!("{}", bytes)), Some("bytes")), + Some(Throughput::Elements(elems)) => (Some(format!("{}", elems)), Some("elements")), + None => (None, None), + }; + let throughput_num = throughput_num.as_ref().map(String::as_str); + + for (count, measured_value) in data.iter_counts().iter().zip(data_scaled.into_iter()) { + let row = CsvRow { + group, + function, + value, + throughput_num, + throughput_type, + sample_measured_value: measured_value, + unit, + iteration_count: (*count) as u64, + }; + self.writer.serialize(row)?; + } + Ok(()) + } +} + +pub struct FileCsvReport; +impl FileCsvReport { + fn write_file( + &self, + path: &Path, + id: &BenchmarkId, + measurements: &MeasurementData<'_>, + formatter: &dyn ValueFormatter, + ) -> Result<()> { + let writer = Writer::from_path(path)?; + let mut writer = CsvReportWriter { writer }; + writer.write_data(id, measurements, formatter)?; + Ok(()) + } +} + +impl Report for FileCsvReport { + fn measurement_complete( + &self, + id: &BenchmarkId, + context: &ReportContext, + measurements: &MeasurementData<'_>, + formatter: &dyn ValueFormatter, + ) { + let mut path = context.output_directory.clone(); + path.push(id.as_directory_name()); + path.push("new"); + path.push("raw.csv"); + log_if_err!(self.write_file(&path, id, measurements, formatter)); + } +} |