1 use criterion::{criterion_group, Criterion, ParameterizedBenchmark};
2 
3 use plotters::coord::Shift;
4 use plotters::prelude::*;
5 use rayon::prelude::*;
6 
7 const SIZES: &'static [u32] = &[100, 400, 800, 1000, 2000];
8 
draw_plot(root: &DrawingArea<BitMapBackend, Shift>, pow: f64)9 fn draw_plot(root: &DrawingArea<BitMapBackend, Shift>, pow: f64) {
10     let mut chart = ChartBuilder::on(root)
11         .caption(format!("y = x^{}", pow), ("Arial", 30))
12         .build_cartesian_2d(-1.0..1.0, -1.0..1.0)
13         .unwrap();
14 
15     chart.configure_mesh().draw().unwrap();
16 
17     chart
18         .draw_series(LineSeries::new(
19             (-50..=50)
20                 .map(|x| x as f64 / 50.0)
21                 .map(|x| (x, x.powf(pow))),
22             &RED,
23         ))
24         .unwrap()
25         .label(format!("y = x^{}", pow))
26         .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &RED));
27     chart
28         .configure_series_labels()
29         .background_style(&WHITE.mix(0.8))
30         .border_style(&BLACK)
31         .draw()
32         .unwrap();
33 }
34 
draw_func_1x1_seq(c: &mut Criterion)35 fn draw_func_1x1_seq(c: &mut Criterion) {
36     c.bench(
37         "draw_func_1x1",
38         ParameterizedBenchmark::new(
39             "sequential",
40             |b, &&s| {
41                 let mut buffer = vec![0; (s * s * 3) as usize];
42                 b.iter(|| {
43                     let root = BitMapBackend::with_buffer(&mut buffer, (s, s)).into_drawing_area();
44                     root.fill(&WHITE).unwrap();
45                     draw_plot(&root, 2.0);
46                 })
47             },
48             SIZES.clone(),
49         ),
50     );
51 }
52 
draw_func_4x4(c: &mut Criterion)53 fn draw_func_4x4(c: &mut Criterion) {
54     c.bench(
55         "draw_func_4x4",
56         ParameterizedBenchmark::new(
57             "sequential",
58             |b, &&s| {
59                 let mut buffer = vec![0; (s * s * 3) as usize];
60                 b.iter(|| {
61                     let root = BitMapBackend::with_buffer(&mut buffer, (s, s)).into_drawing_area();
62                     let areas = root.split_evenly((4, 4));
63                     areas.iter().for_each(|area| draw_plot(&area, 2.0));
64                 })
65             },
66             SIZES.clone(),
67         )
68         .with_function("blit", |b, &&s| {
69             let mut buffer = vec![0; (s * s * 3) as usize];
70             let mut element_buffer = vec![vec![0; (s * s / 4 * 3) as usize]; 4];
71             b.iter(|| {
72                 let root = BitMapBackend::with_buffer(&mut buffer, (s, s)).into_drawing_area();
73                 let areas = root.split_evenly((4, 4));
74                 let elements: Vec<_> = element_buffer
75                     .par_iter_mut()
76                     .map(|b| {
77                         let mut e = BitMapElement::with_mut((0, 0), (s / 2, s / 2), b).unwrap();
78                         draw_plot(&e.as_bitmap_backend().into_drawing_area(), 2.0);
79                         e
80                     })
81                     .collect();
82 
83                 areas
84                     .into_iter()
85                     .zip(elements.into_iter())
86                     .for_each(|(a, e)| a.draw(&e).unwrap());
87             })
88         })
89         .with_function("inplace-blit", |b, &&s| {
90             let mut buffer = vec![0; (s * s * 3) as usize];
91             let mut element_buffer = vec![vec![vec![0; (s * s / 4 * 3) as usize]; 2]; 2];
92             b.iter(|| {
93                 let mut back = BitMapBackend::with_buffer(&mut buffer, (s, s));
94                 back.split(&[s / 2])
95                     .into_iter()
96                     .zip(element_buffer.iter_mut())
97                     .collect::<Vec<_>>()
98                     .into_par_iter()
99                     .for_each(|(back, buffer)| {
100                         let root = back.into_drawing_area();
101                         let areas = root.split_evenly((1, 2));
102 
103                         let elements: Vec<_> = buffer
104                             .par_iter_mut()
105                             .map(|b| {
106                                 let mut e =
107                                     BitMapElement::with_mut((0, 0), (s / 2, s / 2), b).unwrap();
108                                 draw_plot(&e.as_bitmap_backend().into_drawing_area(), 2.0);
109                                 e
110                             })
111                             .collect();
112 
113                         areas
114                             .into_iter()
115                             .zip(elements.into_iter())
116                             .for_each(|(a, e)| a.draw(&e).unwrap())
117                     });
118             })
119         }),
120     );
121 }
122 
draw_func_2x1(c: &mut Criterion)123 fn draw_func_2x1(c: &mut Criterion) {
124     c.bench(
125         "draw_func_2x1",
126         ParameterizedBenchmark::new(
127             "blit",
128             |b, &&s| {
129                 let mut buffer = vec![0; (s * s * 3) as usize];
130                 let mut element_buffer = vec![vec![0; (s * s / 2 * 3) as usize]; 2];
131                 b.iter(|| {
132                     let root = BitMapBackend::with_buffer(&mut buffer, (s, s)).into_drawing_area();
133                     let areas = root.split_evenly((2, 1));
134                     let elements: Vec<_> = element_buffer
135                         .par_iter_mut()
136                         .map(|buf| {
137                             let mut element =
138                                 BitMapElement::with_mut((0, 0), (s, s / 2), buf).unwrap();
139                             draw_plot(&element.as_bitmap_backend().into_drawing_area(), 2.0);
140                             element
141                         })
142                         .collect();
143 
144                     areas
145                         .into_iter()
146                         .zip(elements.into_iter())
147                         .for_each(|(a, e)| a.draw(&e).unwrap());
148                 })
149             },
150             SIZES.clone(),
151         )
152         .with_function("inplace", |b, &&s| {
153             let mut buffer = vec![0; (s * s * 3) as usize];
154             b.iter(|| {
155                 let mut back = BitMapBackend::with_buffer(&mut buffer, (s, s));
156                 back.split(&[s / 2])
157                     .into_par_iter()
158                     .for_each(|b| draw_plot(&b.into_drawing_area(), 2.0));
159             })
160         })
161         .with_function("sequential", |b, &&s| {
162             let mut buffer = vec![0; (s * s * 3) as usize];
163             b.iter(|| {
164                 let root = BitMapBackend::with_buffer(&mut buffer, (s, s)).into_drawing_area();
165                 root.split_evenly((2, 1))
166                     .iter_mut()
167                     .for_each(|area| draw_plot(area, 2.0));
168             })
169         }),
170     );
171 }
172 
173 criterion_group! {
174     name = parallel_group;
175     config = Criterion::default().sample_size(10);
176     targets =
177         draw_func_1x1_seq,
178         draw_func_4x4,
179         draw_func_2x1,
180 }
181