criterion/plot/plotters_backend/
iteration_times.rs

1use super::*;
2
3use std::path::Path;
4
5pub(crate) fn iteration_times_figure(
6    title: Option<&str>,
7    path: &Path,
8    formatter: &dyn ValueFormatter,
9    measurements: &MeasurementData<'_>,
10    size: Option<(u32, u32)>,
11) {
12    let data = &measurements.avg_times;
13    let max_avg_time = data.max();
14    let mut scaled_y: Vec<_> = data.iter().map(|(f, _)| f).collect();
15    let unit = formatter.scale_values(max_avg_time, &mut scaled_y);
16    let scaled_y = Sample::new(&scaled_y);
17
18    let size = size.unwrap_or(SIZE);
19    let root_area = SVGBackend::new(path, size).into_drawing_area();
20
21    let mut cb = ChartBuilder::on(&root_area);
22    if let Some(title) = title {
23        cb.caption(title, (DEFAULT_FONT, 20));
24    }
25
26    let x_range = (1.0)..((data.len() + 1) as f64);
27    let y_range = plotters::data::fitting_range(scaled_y.iter());
28
29    let mut chart = cb
30        .margin((5).percent())
31        .set_label_area_size(LabelAreaPosition::Left, (5).percent_width().min(60))
32        .set_label_area_size(LabelAreaPosition::Bottom, (5).percent_height().min(40))
33        .build_cartesian_2d(x_range, y_range)
34        .unwrap();
35
36    chart
37        .configure_mesh()
38        .y_desc(format!("Average Iteration Time ({})", unit))
39        .x_label_formatter(&|x| pretty_print_float(*x, true))
40        .light_line_style(TRANSPARENT)
41        .draw()
42        .unwrap();
43
44    chart
45        .draw_series(
46            (1..=data.len())
47                .zip(scaled_y.iter())
48                .map(|(x, y)| Circle::new((x as f64, *y), POINT_SIZE, DARK_BLUE.filled())),
49        )
50        .unwrap()
51        .label("Sample")
52        .legend(|(x, y)| Circle::new((x + 10, y), POINT_SIZE, DARK_BLUE.filled()));
53
54    if title.is_some() {
55        chart
56            .configure_series_labels()
57            .position(SeriesLabelPosition::UpperLeft)
58            .draw()
59            .unwrap();
60    }
61}
62
63pub(crate) fn iteration_times_comparison_figure(
64    title: Option<&str>,
65    path: &Path,
66    formatter: &dyn ValueFormatter,
67    measurements: &MeasurementData<'_>,
68    comparison: &ComparisonData,
69    size: Option<(u32, u32)>,
70) {
71    let current_data = &measurements.avg_times;
72    let base_data = &comparison.base_avg_times;
73
74    let mut all_data: Vec<f64> = current_data.iter().map(|(f, _)| f).collect();
75    all_data.extend_from_slice(base_data);
76
77    let typical_value = Sample::new(&all_data).max();
78    let unit = formatter.scale_values(typical_value, &mut all_data);
79
80    let (scaled_current_y, scaled_base_y) = all_data.split_at(current_data.len());
81    let scaled_current_y = Sample::new(scaled_current_y);
82    let scaled_base_y = Sample::new(scaled_base_y);
83
84    let size = size.unwrap_or(SIZE);
85    let root_area = SVGBackend::new(path, size).into_drawing_area();
86
87    let mut cb = ChartBuilder::on(&root_area);
88    if let Some(title) = title {
89        cb.caption(title, (DEFAULT_FONT, 20));
90    }
91
92    let max_samples = current_data.len().max(base_data.len()) as f64;
93
94    let y_range = plotters::data::fitting_range(all_data.iter());
95
96    let mut chart = cb
97        .margin((5).percent())
98        .set_label_area_size(LabelAreaPosition::Left, (5).percent_width().min(60))
99        .set_label_area_size(LabelAreaPosition::Bottom, (5).percent_height().min(40))
100        .build_cartesian_2d(0.0..max_samples, y_range)
101        .unwrap();
102
103    chart
104        .configure_mesh()
105        .y_desc(format!("Average Iteration Time ({})", unit))
106        .x_label_formatter(&|x| pretty_print_float(*x, true))
107        .light_line_style(TRANSPARENT)
108        .draw()
109        .unwrap();
110
111    chart
112        .draw_series(
113            (1..=current_data.len())
114                .zip(scaled_current_y.iter())
115                .map(|(x, y)| Circle::new((x as f64, *y), POINT_SIZE, DARK_BLUE.filled())),
116        )
117        .unwrap()
118        .label("Current")
119        .legend(|(x, y)| Circle::new((x + 10, y), POINT_SIZE, DARK_BLUE.filled()));
120
121    chart
122        .draw_series(
123            (1..=base_data.len())
124                .zip(scaled_base_y.iter())
125                .map(|(x, y)| Circle::new((x as f64, *y), POINT_SIZE, DARK_RED.filled())),
126        )
127        .unwrap()
128        .label("Base")
129        .legend(|(x, y)| Circle::new((x + 10, y), POINT_SIZE, DARK_RED.filled()));
130
131    if title.is_some() {
132        chart
133            .configure_series_labels()
134            .position(SeriesLabelPosition::UpperLeft)
135            .draw()
136            .unwrap();
137    }
138}