criterion/plot/gnuplot_backend/
iteration_times.rs

1use std::process::Child;
2
3use criterion_plot::prelude::*;
4
5use super::*;
6use crate::report::{BenchmarkId, ComparisonData, MeasurementData, ReportContext};
7
8use crate::measurement::ValueFormatter;
9
10fn iteration_times_figure(
11    formatter: &dyn ValueFormatter,
12    measurements: &MeasurementData<'_>,
13    size: Option<Size>,
14) -> Figure {
15    let data = &measurements.avg_times;
16    let max_avg_time = data.max();
17    let mut scaled_y: Vec<_> = data.iter().map(|(f, _)| f).collect();
18    let unit = formatter.scale_values(max_avg_time, &mut scaled_y);
19    let scaled_y = Sample::new(&scaled_y);
20
21    let mut figure = Figure::new();
22    figure
23        .set(Font(DEFAULT_FONT))
24        .set(size.unwrap_or(SIZE))
25        .configure(Axis::BottomX, |a| {
26            a.configure(Grid::Major, |g| g.show()).set(Label("Sample"))
27        })
28        .configure(Axis::LeftY, |a| {
29            a.configure(Grid::Major, |g| g.show())
30                .set(Label(format!("Average Iteration Time ({})", unit)))
31        })
32        .plot(
33            Points {
34                x: 1..(data.len() + 1),
35                y: scaled_y.as_ref(),
36            },
37            |c| {
38                c.set(DARK_BLUE)
39                    .set(PointSize(0.5))
40                    .set(PointType::FilledCircle)
41            },
42        );
43    figure
44}
45
46pub(crate) fn iteration_times(
47    id: &BenchmarkId,
48    context: &ReportContext,
49    formatter: &dyn ValueFormatter,
50    measurements: &MeasurementData<'_>,
51    size: Option<Size>,
52) -> Child {
53    let mut figure = iteration_times_figure(formatter, measurements, size);
54    figure.set(Title(gnuplot_escape(id.as_title())));
55    figure.configure(Key, |k| {
56        k.set(Justification::Left)
57            .set(Order::SampleText)
58            .set(Position::Inside(Vertical::Top, Horizontal::Left))
59    });
60
61    let path = context.report_path(id, "iteration_times.svg");
62    debug_script(&path, &figure);
63    figure.set(Output(path)).draw().unwrap()
64}
65
66pub(crate) fn iteration_times_small(
67    id: &BenchmarkId,
68    context: &ReportContext,
69    formatter: &dyn ValueFormatter,
70    measurements: &MeasurementData<'_>,
71    size: Option<Size>,
72) -> Child {
73    let mut figure = iteration_times_figure(formatter, measurements, size);
74    figure.configure(Key, |k| k.hide());
75
76    let path = context.report_path(id, "iteration_times_small.svg");
77    debug_script(&path, &figure);
78    figure.set(Output(path)).draw().unwrap()
79}
80
81fn iteration_times_comparison_figure(
82    formatter: &dyn ValueFormatter,
83    measurements: &MeasurementData<'_>,
84    comparison: &ComparisonData,
85    size: Option<Size>,
86) -> Figure {
87    let current_data = &measurements.avg_times;
88    let base_data = &comparison.base_avg_times;
89
90    let mut all_data: Vec<f64> = current_data.iter().map(|(f, _)| f).collect();
91    all_data.extend_from_slice(base_data);
92
93    let typical_value = Sample::new(&all_data).max();
94    let unit = formatter.scale_values(typical_value, &mut all_data);
95
96    let (scaled_current_y, scaled_base_y) = all_data.split_at(current_data.len());
97    let scaled_current_y = Sample::new(scaled_current_y);
98    let scaled_base_y = Sample::new(scaled_base_y);
99
100    let mut figure = Figure::new();
101    figure
102        .set(Font(DEFAULT_FONT))
103        .set(size.unwrap_or(SIZE))
104        .configure(Axis::BottomX, |a| {
105            a.configure(Grid::Major, |g| g.show()).set(Label("Sample"))
106        })
107        .configure(Axis::LeftY, |a| {
108            a.configure(Grid::Major, |g| g.show())
109                .set(Label(format!("Average Iteration Time ({})", unit)))
110        })
111        .configure(Key, |k| {
112            k.set(Justification::Left)
113                .set(Order::SampleText)
114                .set(Position::Inside(Vertical::Top, Horizontal::Left))
115        })
116        .plot(
117            Points {
118                x: 1..(current_data.len() + 1),
119                y: scaled_base_y.as_ref(),
120            },
121            |c| {
122                c.set(DARK_RED)
123                    .set(Label("Base"))
124                    .set(PointSize(0.5))
125                    .set(PointType::FilledCircle)
126            },
127        )
128        .plot(
129            Points {
130                x: 1..(current_data.len() + 1),
131                y: scaled_current_y.as_ref(),
132            },
133            |c| {
134                c.set(DARK_BLUE)
135                    .set(Label("Current"))
136                    .set(PointSize(0.5))
137                    .set(PointType::FilledCircle)
138            },
139        );
140    figure
141}
142
143pub(crate) fn iteration_times_comparison(
144    id: &BenchmarkId,
145    context: &ReportContext,
146    formatter: &dyn ValueFormatter,
147    measurements: &MeasurementData<'_>,
148    comparison: &ComparisonData,
149    size: Option<Size>,
150) -> Child {
151    let mut figure = iteration_times_comparison_figure(formatter, measurements, comparison, size);
152    figure.set(Title(gnuplot_escape(id.as_title())));
153
154    let path = context.report_path(id, "both/iteration_times.svg");
155    debug_script(&path, &figure);
156    figure.set(Output(path)).draw().unwrap()
157}
158
159pub(crate) fn iteration_times_comparison_small(
160    id: &BenchmarkId,
161    context: &ReportContext,
162    formatter: &dyn ValueFormatter,
163    measurements: &MeasurementData<'_>,
164    comparison: &ComparisonData,
165    size: Option<Size>,
166) -> Child {
167    let mut figure = iteration_times_comparison_figure(formatter, measurements, comparison, size);
168    figure.configure(Key, |k| k.hide());
169
170    let path = context.report_path(id, "relative_iteration_times_small.svg");
171    debug_script(&path, &figure);
172    figure.set(Output(path)).draw().unwrap()
173}