aboutsummaryrefslogtreecommitdiff
path: root/src/csv_report.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/csv_report.rs')
-rwxr-xr-xsrc/csv_report.rs90
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));
+ }
+}