1 use super::{PlotContext, PlotData, Plotter};
2 use crate::measurement::ValueFormatter;
3 use crate::report::{BenchmarkId, ComparisonData, MeasurementData, ValueType};
4 use plotters::data::float::pretty_print_float;
5 use plotters::prelude::*;
6 
7 use crate::kde;
8 use crate::stats::bivariate::Data;
9 use crate::stats::univariate::Sample;
10 
11 static DEFAULT_FONT: FontFamily = FontFamily::SansSerif;
12 static KDE_POINTS: usize = 500;
13 static SIZE: (u32, u32) = (960, 540);
14 static POINT_SIZE: u32 = 3;
15 
16 const DARK_BLUE: RGBColor = RGBColor(31, 120, 180);
17 const DARK_ORANGE: RGBColor = RGBColor(255, 127, 0);
18 const DARK_RED: RGBColor = RGBColor(227, 26, 28);
19 
20 mod distributions;
21 mod iteration_times;
22 mod pdf;
23 mod regression;
24 mod summary;
25 mod t_test;
26 
convert_size(size: Option<(usize, usize)>) -> Option<(u32, u32)>27 fn 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)]
34 pub struct PlottersBackend;
35 
36 #[allow(unused_variables)]
37 impl Plotter for PlottersBackend {
pdf(&mut self, ctx: PlotContext<'_>, data: PlotData<'_>)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 
regression(&mut self, ctx: PlotContext<'_>, data: PlotData<'_>)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 
iteration_times(&mut self, ctx: PlotContext<'_>, data: PlotData<'_>)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 
abs_distributions(&mut self, ctx: PlotContext<'_>, data: PlotData<'_>)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 
rel_distributions(&mut self, ctx: PlotContext<'_>, data: PlotData<'_>)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 
line_comparison( &mut self, ctx: PlotContext<'_>, formatter: &dyn ValueFormatter, all_curves: &[&(&BenchmarkId, Vec<f64>)], value_type: ValueType, )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 
violin( &mut self, ctx: PlotContext<'_>, formatter: &dyn ValueFormatter, all_curves: &[&(&BenchmarkId, Vec<f64>)], )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 
t_test(&mut self, ctx: PlotContext<'_>, data: PlotData<'_>)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 
wait(&mut self)231     fn wait(&mut self) {}
232 }
233