criterion/plot/plotters_backend/
mod.rs

1use super::{PlotContext, PlotData, Plotter};
2use crate::measurement::ValueFormatter;
3use crate::report::{BenchmarkId, ComparisonData, MeasurementData, ValueType};
4use plotters::data::float::pretty_print_float;
5use plotters::prelude::*;
6
7use crate::kde;
8use crate::stats::bivariate::Data;
9use crate::stats::univariate::Sample;
10
11static DEFAULT_FONT: FontFamily = FontFamily::SansSerif;
12static KDE_POINTS: usize = 500;
13static SIZE: (u32, u32) = (960, 540);
14static POINT_SIZE: u32 = 3;
15
16const DARK_BLUE: RGBColor = RGBColor(31, 120, 180);
17const DARK_ORANGE: RGBColor = RGBColor(255, 127, 0);
18const DARK_RED: RGBColor = RGBColor(227, 26, 28);
19
20mod distributions;
21mod iteration_times;
22mod pdf;
23mod regression;
24mod summary;
25mod t_test;
26
27fn convert_size(size: Option<(usize, usize)>) -> Option<(u32, u32)> {
28    if let Some((w, h)) = size {
29        return Some((w as u32, h as u32));
30    }
31    None
32}
33#[derive(Default)]
34pub struct PlottersBackend;
35
36#[allow(unused_variables)]
37impl Plotter for PlottersBackend {
38    fn pdf(&mut self, ctx: PlotContext<'_>, data: PlotData<'_>) {
39        if let Some(cmp) = data.comparison {
40            let (path, title) = if ctx.is_thumbnail {
41                (
42                    ctx.context.report_path(ctx.id, "relative_pdf_small.svg"),
43                    None,
44                )
45            } else {
46                (
47                    ctx.context.report_path(ctx.id, "both/pdf.svg"),
48                    Some(ctx.id.as_title()),
49                )
50            };
51            pdf::pdf_comparison_figure(
52                path.as_ref(),
53                title,
54                data.formatter,
55                data.measurements,
56                cmp,
57                convert_size(ctx.size),
58            );
59            return;
60        }
61        if ctx.is_thumbnail {
62            pdf::pdf_small(
63                ctx.id,
64                ctx.context,
65                data.formatter,
66                data.measurements,
67                convert_size(ctx.size),
68            );
69        } else {
70            pdf::pdf(
71                ctx.id,
72                ctx.context,
73                data.formatter,
74                data.measurements,
75                convert_size(ctx.size),
76            );
77        }
78    }
79
80    fn regression(&mut self, ctx: PlotContext<'_>, data: PlotData<'_>) {
81        let (title, path) = match (data.comparison.is_some(), ctx.is_thumbnail) {
82            (true, true) => (
83                None,
84                ctx.context
85                    .report_path(ctx.id, "relative_regression_small.svg"),
86            ),
87            (true, false) => (
88                Some(ctx.id.as_title()),
89                ctx.context.report_path(ctx.id, "both/regression.svg"),
90            ),
91            (false, true) => (
92                None,
93                ctx.context.report_path(ctx.id, "regression_small.svg"),
94            ),
95            (false, false) => (
96                Some(ctx.id.as_title()),
97                ctx.context.report_path(ctx.id, "regression.svg"),
98            ),
99        };
100
101        if let Some(cmp) = data.comparison {
102            let base_data = Data::new(&cmp.base_iter_counts, &cmp.base_sample_times);
103            regression::regression_comparison_figure(
104                title,
105                path.as_path(),
106                data.formatter,
107                data.measurements,
108                cmp,
109                &base_data,
110                convert_size(ctx.size),
111            );
112        } else {
113            regression::regression_figure(
114                title,
115                path.as_path(),
116                data.formatter,
117                data.measurements,
118                convert_size(ctx.size),
119            );
120        }
121    }
122
123    fn iteration_times(&mut self, ctx: PlotContext<'_>, data: PlotData<'_>) {
124        let (title, path) = match (data.comparison.is_some(), ctx.is_thumbnail) {
125            (true, true) => (
126                None,
127                ctx.context
128                    .report_path(ctx.id, "relative_iteration_times_small.svg"),
129            ),
130            (true, false) => (
131                Some(ctx.id.as_title()),
132                ctx.context.report_path(ctx.id, "both/iteration_times.svg"),
133            ),
134            (false, true) => (
135                None,
136                ctx.context.report_path(ctx.id, "iteration_times_small.svg"),
137            ),
138            (false, false) => (
139                Some(ctx.id.as_title()),
140                ctx.context.report_path(ctx.id, "iteration_times.svg"),
141            ),
142        };
143
144        if let Some(cmp) = data.comparison {
145            let base_data = Data::new(&cmp.base_iter_counts, &cmp.base_sample_times);
146            iteration_times::iteration_times_comparison_figure(
147                title,
148                path.as_path(),
149                data.formatter,
150                data.measurements,
151                cmp,
152                convert_size(ctx.size),
153            );
154        } else {
155            iteration_times::iteration_times_figure(
156                title,
157                path.as_path(),
158                data.formatter,
159                data.measurements,
160                convert_size(ctx.size),
161            );
162        }
163    }
164
165    fn abs_distributions(&mut self, ctx: PlotContext<'_>, data: PlotData<'_>) {
166        distributions::abs_distributions(
167            ctx.id,
168            ctx.context,
169            data.formatter,
170            data.measurements,
171            convert_size(ctx.size),
172        );
173    }
174
175    fn rel_distributions(&mut self, ctx: PlotContext<'_>, data: PlotData<'_>) {
176        distributions::rel_distributions(
177            ctx.id,
178            ctx.context,
179            data.measurements,
180            data.comparison.unwrap(),
181            convert_size(ctx.size),
182        );
183    }
184
185    fn line_comparison(
186        &mut self,
187        ctx: PlotContext<'_>,
188        formatter: &dyn ValueFormatter,
189        all_curves: &[&(&BenchmarkId, Vec<f64>)],
190        value_type: ValueType,
191    ) {
192        let path = ctx.line_comparison_path();
193        summary::line_comparison(
194            formatter,
195            ctx.id.as_title(),
196            all_curves,
197            &path,
198            value_type,
199            ctx.context.plot_config.summary_scale,
200        );
201    }
202
203    fn violin(
204        &mut self,
205        ctx: PlotContext<'_>,
206        formatter: &dyn ValueFormatter,
207        all_curves: &[&(&BenchmarkId, Vec<f64>)],
208    ) {
209        let violin_path = ctx.violin_path();
210
211        summary::violin(
212            formatter,
213            ctx.id.as_title(),
214            all_curves,
215            &violin_path,
216            ctx.context.plot_config.summary_scale,
217        );
218    }
219
220    fn t_test(&mut self, ctx: PlotContext<'_>, data: PlotData<'_>) {
221        let title = ctx.id.as_title();
222        let path = ctx.context.report_path(ctx.id, "change/t-test.svg");
223        t_test::t_test(
224            path.as_path(),
225            title,
226            data.comparison.unwrap(),
227            convert_size(ctx.size),
228        );
229    }
230
231    fn wait(&mut self) {}
232}