use std::process::Child; use criterion_plot::prelude::*; use super::*; use crate::report::{BenchmarkId, ComparisonData, MeasurementData, ReportContext}; use crate::measurement::ValueFormatter; fn iteration_times_figure( formatter: &dyn ValueFormatter, measurements: &MeasurementData<'_>, size: Option, ) -> Figure { let data = &measurements.avg_times; let max_avg_time = data.max(); let mut scaled_y: Vec<_> = data.iter().map(|(f, _)| f).collect(); let unit = formatter.scale_values(max_avg_time, &mut scaled_y); let scaled_y = Sample::new(&scaled_y); let mut figure = Figure::new(); figure .set(Font(DEFAULT_FONT)) .set(size.unwrap_or(SIZE)) .configure(Axis::BottomX, |a| { a.configure(Grid::Major, |g| g.show()).set(Label("Sample")) }) .configure(Axis::LeftY, |a| { a.configure(Grid::Major, |g| g.show()) .set(Label(format!("Average Iteration Time ({})", unit))) }) .plot( Points { x: 1..(data.len() + 1), y: scaled_y.as_ref(), }, |c| { c.set(DARK_BLUE) .set(PointSize(0.5)) .set(PointType::FilledCircle) }, ); figure } pub(crate) fn iteration_times( id: &BenchmarkId, context: &ReportContext, formatter: &dyn ValueFormatter, measurements: &MeasurementData<'_>, size: Option, ) -> Child { let mut figure = iteration_times_figure(formatter, measurements, size); figure.set(Title(gnuplot_escape(id.as_title()))); figure.configure(Key, |k| { k.set(Justification::Left) .set(Order::SampleText) .set(Position::Inside(Vertical::Top, Horizontal::Left)) }); let path = context.report_path(id, "iteration_times.svg"); debug_script(&path, &figure); figure.set(Output(path)).draw().unwrap() } pub(crate) fn iteration_times_small( id: &BenchmarkId, context: &ReportContext, formatter: &dyn ValueFormatter, measurements: &MeasurementData<'_>, size: Option, ) -> Child { let mut figure = iteration_times_figure(formatter, measurements, size); figure.configure(Key, |k| k.hide()); let path = context.report_path(id, "iteration_times_small.svg"); debug_script(&path, &figure); figure.set(Output(path)).draw().unwrap() } fn iteration_times_comparison_figure( formatter: &dyn ValueFormatter, measurements: &MeasurementData<'_>, comparison: &ComparisonData, size: Option, ) -> Figure { let current_data = &measurements.avg_times; let base_data = &comparison.base_avg_times; let mut all_data: Vec = current_data.iter().map(|(f, _)| f).collect(); all_data.extend_from_slice(base_data); let typical_value = Sample::new(&all_data).max(); let unit = formatter.scale_values(typical_value, &mut all_data); let (scaled_current_y, scaled_base_y) = all_data.split_at(current_data.len()); let scaled_current_y = Sample::new(scaled_current_y); let scaled_base_y = Sample::new(scaled_base_y); let mut figure = Figure::new(); figure .set(Font(DEFAULT_FONT)) .set(size.unwrap_or(SIZE)) .configure(Axis::BottomX, |a| { a.configure(Grid::Major, |g| g.show()).set(Label("Sample")) }) .configure(Axis::LeftY, |a| { a.configure(Grid::Major, |g| g.show()) .set(Label(format!("Average Iteration Time ({})", unit))) }) .configure(Key, |k| { k.set(Justification::Left) .set(Order::SampleText) .set(Position::Inside(Vertical::Top, Horizontal::Left)) }) .plot( Points { x: 1..(current_data.len() + 1), y: scaled_base_y.as_ref(), }, |c| { c.set(DARK_RED) .set(Label("Base")) .set(PointSize(0.5)) .set(PointType::FilledCircle) }, ) .plot( Points { x: 1..(current_data.len() + 1), y: scaled_current_y.as_ref(), }, |c| { c.set(DARK_BLUE) .set(Label("Current")) .set(PointSize(0.5)) .set(PointType::FilledCircle) }, ); figure } pub(crate) fn iteration_times_comparison( id: &BenchmarkId, context: &ReportContext, formatter: &dyn ValueFormatter, measurements: &MeasurementData<'_>, comparison: &ComparisonData, size: Option, ) -> Child { let mut figure = iteration_times_comparison_figure(formatter, measurements, comparison, size); figure.set(Title(gnuplot_escape(id.as_title()))); let path = context.report_path(id, "both/iteration_times.svg"); debug_script(&path, &figure); figure.set(Output(path)).draw().unwrap() } pub(crate) fn iteration_times_comparison_small( id: &BenchmarkId, context: &ReportContext, formatter: &dyn ValueFormatter, measurements: &MeasurementData<'_>, comparison: &ComparisonData, size: Option, ) -> Child { let mut figure = iteration_times_comparison_figure(formatter, measurements, comparison, size); figure.configure(Key, |k| k.hide()); let path = context.report_path(id, "relative_iteration_times_small.svg"); debug_script(&path, &figure); figure.set(Output(path)).draw().unwrap() }