diff options
Diffstat (limited to 'benches')
-rw-r--r-- | benches/benches/data.rs | 37 | ||||
-rw-r--r-- | benches/benches/mod.rs | 3 | ||||
-rw-r--r-- | benches/benches/parallel.rs | 180 | ||||
-rw-r--r-- | benches/benches/rasterizer.rs | 204 | ||||
-rw-r--r-- | benches/main.rs | 9 |
5 files changed, 433 insertions, 0 deletions
diff --git a/benches/benches/data.rs b/benches/benches/data.rs new file mode 100644 index 0000000..22dc9f4 --- /dev/null +++ b/benches/benches/data.rs @@ -0,0 +1,37 @@ +use criterion::{criterion_group, Criterion}; +use plotters::data::Quartiles; + +struct Lcg { + state: u32, +} + +impl Lcg { + fn new() -> Lcg { + Lcg { state: 0 } + } +} + +impl Iterator for Lcg { + type Item = u32; + + fn next(&mut self) -> Option<u32> { + self.state = self.state.wrapping_mul(1_103_515_245).wrapping_add(12_345); + self.state %= 1 << 31; + Some(self.state) + } +} + +fn quartiles_calc(c: &mut Criterion) { + let src: Vec<u32> = Lcg::new().take(100000).collect(); + c.bench_function("data::quartiles_calc", |b| { + b.iter(|| { + Quartiles::new(&src); + }) + }); +} + +criterion_group! { + name = quartiles_group; + config = Criterion::default().sample_size(10); + targets = quartiles_calc +} diff --git a/benches/benches/mod.rs b/benches/benches/mod.rs new file mode 100644 index 0000000..0967b2d --- /dev/null +++ b/benches/benches/mod.rs @@ -0,0 +1,3 @@ +pub mod data; +pub mod parallel; +pub mod rasterizer; diff --git a/benches/benches/parallel.rs b/benches/benches/parallel.rs new file mode 100644 index 0000000..7bd37d0 --- /dev/null +++ b/benches/benches/parallel.rs @@ -0,0 +1,180 @@ +use criterion::{criterion_group, Criterion, ParameterizedBenchmark}; + +use plotters::coord::Shift; +use plotters::prelude::*; +use rayon::prelude::*; + +const SIZES: &'static [u32] = &[100, 400, 800, 1000, 2000]; + +fn draw_plot(root: &DrawingArea<BitMapBackend, Shift>, pow: f64) { + let mut chart = ChartBuilder::on(root) + .caption(format!("y = x^{}", pow), ("Arial", 30)) + .build_ranged(-1.0..1.0, -1.0..1.0) + .unwrap(); + + chart.configure_mesh().draw().unwrap(); + + chart + .draw_series(LineSeries::new( + (-50..=50) + .map(|x| x as f64 / 50.0) + .map(|x| (x, x.powf(pow))), + &RED, + )) + .unwrap() + .label(format!("y = x^{}", pow)) + .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &RED)); + chart + .configure_series_labels() + .background_style(&WHITE.mix(0.8)) + .border_style(&BLACK) + .draw() + .unwrap(); +} + +fn draw_func_1x1_seq(c: &mut Criterion) { + c.bench( + "draw_func_1x1", + ParameterizedBenchmark::new( + "sequential", + |b, &&s| { + let mut buffer = vec![0; (s * s * 3) as usize]; + b.iter(|| { + let root = BitMapBackend::with_buffer(&mut buffer, (s, s)).into_drawing_area(); + root.fill(&WHITE).unwrap(); + draw_plot(&root, 2.0); + }) + }, + SIZES.clone(), + ), + ); +} + +fn draw_func_4x4(c: &mut Criterion) { + c.bench( + "draw_func_4x4", + ParameterizedBenchmark::new( + "sequential", + |b, &&s| { + let mut buffer = vec![0; (s * s * 3) as usize]; + b.iter(|| { + let root = BitMapBackend::with_buffer(&mut buffer, (s, s)).into_drawing_area(); + let areas = root.split_evenly((4, 4)); + areas.iter().for_each(|area| draw_plot(&area, 2.0)); + }) + }, + SIZES.clone(), + ) + .with_function("blit", |b, &&s| { + let mut buffer = vec![0; (s * s * 3) as usize]; + let mut element_buffer = vec![vec![0; (s * s / 4 * 3) as usize]; 4]; + b.iter(|| { + let root = BitMapBackend::with_buffer(&mut buffer, (s, s)).into_drawing_area(); + let areas = root.split_evenly((4, 4)); + let elements: Vec<_> = element_buffer + .par_iter_mut() + .map(|b| { + let mut e = BitMapElement::with_mut((0, 0), (s / 2, s / 2), b).unwrap(); + draw_plot(&e.as_bitmap_backend().into_drawing_area(), 2.0); + e + }) + .collect(); + + areas + .into_iter() + .zip(elements.into_iter()) + .for_each(|(a, e)| a.draw(&e).unwrap()); + }) + }) + .with_function("inplace-blit", |b, &&s| { + let mut buffer = vec![0; (s * s * 3) as usize]; + let mut element_buffer = vec![vec![vec![0; (s * s / 4 * 3) as usize]; 2]; 2]; + b.iter(|| { + let mut back = BitMapBackend::with_buffer(&mut buffer, (s, s)); + back.split(&[s / 2]) + .into_iter() + .zip(element_buffer.iter_mut()) + .collect::<Vec<_>>() + .into_par_iter() + .for_each(|(back, buffer)| { + let root = back.into_drawing_area(); + let areas = root.split_evenly((1, 2)); + + let elements: Vec<_> = buffer + .par_iter_mut() + .map(|b| { + let mut e = + BitMapElement::with_mut((0, 0), (s / 2, s / 2), b).unwrap(); + draw_plot(&e.as_bitmap_backend().into_drawing_area(), 2.0); + e + }) + .collect(); + + areas + .into_iter() + .zip(elements.into_iter()) + .for_each(|(a, e)| a.draw(&e).unwrap()) + }); + }) + }), + ); +} + +fn draw_func_2x1(c: &mut Criterion) { + c.bench( + "draw_func_2x1", + ParameterizedBenchmark::new( + "blit", + |b, &&s| { + let mut buffer = vec![0; (s * s * 3) as usize]; + let mut element_buffer = vec![vec![0; (s * s / 2 * 3) as usize]; 2]; + b.iter(|| { + let root = BitMapBackend::with_buffer(&mut buffer, (s, s)).into_drawing_area(); + let areas = root.split_evenly((2, 1)); + let elements: Vec<_> = element_buffer + .par_iter_mut() + .map(|buf| { + let mut element = + BitMapElement::with_mut((0, 0), (s, s / 2), buf).unwrap(); + draw_plot(&element.as_bitmap_backend().into_drawing_area(), 2.0); + element + }) + .collect(); + + areas + .into_iter() + .zip(elements.into_iter()) + .for_each(|(a, e)| a.draw(&e).unwrap()); + }) + }, + SIZES.clone(), + ) + .with_function("inplace", |b, &&s| { + let mut buffer = vec![0; (s * s * 3) as usize]; + b.iter(|| { + let mut back = BitMapBackend::with_buffer(&mut buffer, (s, s)); + back.split(&[s / 2]) + .into_par_iter() + .for_each(|b| draw_plot(&b.into_drawing_area(), 2.0)); + }) + }) + .with_function("sequential", |b, &&s| { + let mut buffer = vec![0; (s * s * 3) as usize]; + b.iter(|| { + let root = BitMapBackend::with_buffer(&mut buffer, (s, s)).into_drawing_area(); + root.split_evenly((2, 1)) + .iter_mut() + .for_each(|area| draw_plot(area, 2.0)); + }) + }), + ); +} + +criterion_group! { + name = parallel_group; + config = Criterion::default().sample_size(10); + targets = + draw_func_1x1_seq, + draw_func_4x4, + draw_func_2x1, +} diff --git a/benches/benches/rasterizer.rs b/benches/benches/rasterizer.rs new file mode 100644 index 0000000..405acb1 --- /dev/null +++ b/benches/benches/rasterizer.rs @@ -0,0 +1,204 @@ +use criterion::{criterion_group, Criterion}; +use plotters::drawing::bitmap_pixel::BGRXPixel; +use plotters::prelude::*; + +const W: u32 = 1000; +const H: u32 = 1000; + +fn draw_pixel(c: &mut Criterion) { + let mut group = c.benchmark_group("rasterizer::draw_pixel"); + + group.bench_function("rgb", |b| { + let mut buffer = vec![0; (W * H * 3) as usize]; + b.iter(|| { + let mut root = BitMapBackend::with_buffer(&mut buffer, (W, H)); + for x in 0..W / 10 { + for y in 0..H / 10 { + root.draw_pixel((x as i32, y as i32), &RGBColor(255, 0, 234).to_rgba()) + .unwrap(); + } + } + }) + }); + + group.bench_function("xbgr", |b| { + let mut buffer = vec![0; (W * H * 4) as usize]; + b.iter(|| { + let mut root = + BitMapBackend::<BGRXPixel>::with_buffer_and_format(&mut buffer, (W, H)).unwrap(); + for x in 0..W / 10 { + for y in 0..H / 10 { + root.draw_pixel((x as i32, y as i32), &RGBColor(255, 0, 234).to_rgba()) + .unwrap(); + } + } + }) + }); +} + +fn draw_line(c: &mut Criterion) { + let mut group = c.benchmark_group("rasterizer::draw_line"); + + group.bench_function("rgb", |b| { + let mut buffer = vec![0; (W * H * 3) as usize]; + b.iter(|| { + let mut root = BitMapBackend::with_buffer(&mut buffer, (W, H)); + for y in 0..10 { + root.draw_line( + (0, 0), + ((W / 2) as i32, (y * 100) as i32), + &RGBColor(255, 0, 234).to_rgba(), + ) + .unwrap(); + } + }) + }); + + group.bench_function("bgrx", |b| { + let mut buffer = vec![0; (W * H * 4) as usize]; + b.iter(|| { + let mut root = + BitMapBackend::<BGRXPixel>::with_buffer_and_format(&mut buffer, (W, H)).unwrap(); + for y in 0..10 { + root.draw_line( + (0, 0), + ((W / 2) as i32, (y * 100) as i32), + &RGBColor(255, 0, 234).to_rgba(), + ) + .unwrap(); + } + }) + }); +} + +fn fill_background(c: &mut Criterion) { + let mut group = c.benchmark_group("rasterizer::fill_background"); + + group.bench_function("rgb", |b| { + let mut buffer = vec![0; (W * H * 3) as usize]; + b.iter(|| { + let root = BitMapBackend::with_buffer(&mut buffer, (W, H)).into_drawing_area(); + root.fill(&WHITE).unwrap(); + }) + }); + + group.bench_function("bgrx", |b| { + let mut buffer = vec![0; (W * H * 4) as usize]; + b.iter(|| { + let root = BitMapBackend::<BGRXPixel>::with_buffer_and_format(&mut buffer, (W, H)) + .unwrap() + .into_drawing_area(); + root.fill(&WHITE).unwrap(); + }) + }); +} + +fn blend_background(c: &mut Criterion) { + let mut g = c.benchmark_group("rasterizer::blend_background"); + + g.bench_function("rgb", |b| { + let mut buffer = vec![0; (W * H * 3) as usize]; + b.iter(|| { + let root = BitMapBackend::with_buffer(&mut buffer, (W, H)).into_drawing_area(); + root.fill(&WHITE.mix(0.1)).unwrap(); + }) + }); + + g.bench_function("bgrx", |b| { + let mut buffer = vec![0; (W * H * 4) as usize]; + b.iter(|| { + let root = BitMapBackend::<BGRXPixel>::with_buffer_and_format(&mut buffer, (W, H)) + .unwrap() + .into_drawing_area(); + root.fill(&WHITE.mix(0.1)).unwrap(); + }) + }); +} + +fn fill_circle(c: &mut Criterion) { + let mut g = c.benchmark_group("rasterizer::fill_circle"); + + g.bench_function("rgb", |b| { + let mut buffer = vec![0; (W * H * 3) as usize]; + b.iter(|| { + let mut root = BitMapBackend::with_buffer(&mut buffer, (W, H)); + root.draw_circle((W as i32 / 2, H as i32 / 2), W / 2, &WHITE.to_rgba(), true) + .unwrap(); + }) + }); + + g.bench_function("bgrx", |b| { + let mut buffer = vec![0; (W * H * 4) as usize]; + b.iter(|| { + let mut root = + BitMapBackend::<BGRXPixel>::with_buffer_and_format(&mut buffer, (W, H)).unwrap(); + root.draw_circle((W as i32 / 2, H as i32 / 2), W / 2, &WHITE.to_rgba(), true) + .unwrap(); + }) + }); +} + +fn fill_background_red(c: &mut Criterion) { + let mut g = c.benchmark_group("rasterizer::fill_background_red"); + + g.bench_function("rgb", |b| { + let mut buffer = vec![0; (W * H * 3) as usize]; + b.iter(|| { + let root = BitMapBackend::with_buffer(&mut buffer, (W, H)).into_drawing_area(); + root.fill(&RED).unwrap(); + }) + }); + + g.bench_function("bgrx", |b| { + let mut buffer = vec![0; (W * H * 4) as usize]; + b.iter(|| { + let root = BitMapBackend::<BGRXPixel>::with_buffer_and_format(&mut buffer, (W, H)) + .unwrap() + .into_drawing_area(); + root.fill(&RED).unwrap(); + }) + }); +} + +fn fill_hexagon(c: &mut Criterion) { + let mut g = c.benchmark_group("rasterizer::fill_hexagon"); + let mut vert = vec![]; + + for i in 0..6 { + let x = (W as f64 / 5.0 * (std::f64::consts::PI * i as f64 / 3.0).cos()).ceil() as i32 + + W as i32 / 2; + let y = (W as f64 / 5.0 * (std::f64::consts::PI * i as f64 / 3.0).sin()).ceil() as i32 + + W as i32 / 2; + vert.push((x, y)); + } + + g.bench_function("rgb", |b| { + let mut buffer = vec![0; (W * H * 3) as usize]; + b.iter(|| { + let mut root = BitMapBackend::with_buffer(&mut buffer, (W, H)); + root.fill_polygon(vert.clone(), &RED).unwrap(); + }) + }); + + g.bench_function("bgrx", |b| { + let mut buffer = vec![0; (W * H * 4) as usize]; + b.iter(|| { + let mut root = + BitMapBackend::<BGRXPixel>::with_buffer_and_format(&mut buffer, (W, H)).unwrap(); + root.fill_polygon(vert.clone(), &RED).unwrap(); + }) + }); +} + +criterion_group! { + name = rasterizer_group; + config = Criterion::default(); + targets = + blend_background, + draw_pixel, + draw_line, + fill_background, + fill_circle, + fill_background_red, + fill_hexagon, +} diff --git a/benches/main.rs b/benches/main.rs new file mode 100644 index 0000000..3ebf8e8 --- /dev/null +++ b/benches/main.rs @@ -0,0 +1,9 @@ +use criterion::criterion_main; + +mod benches; + +criterion_main! { + benches::parallel::parallel_group, + benches::rasterizer::rasterizer_group, + benches::data::quartiles_group +} |