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 | |
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 { |
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 | } |
233 | |