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