criterion/plot/gnuplot_backend/
iteration_times.rs

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