aboutsummaryrefslogtreecommitdiff
path: root/benches
diff options
context:
space:
mode:
Diffstat (limited to 'benches')
-rw-r--r--benches/benches/data.rs37
-rw-r--r--benches/benches/mod.rs3
-rw-r--r--benches/benches/parallel.rs180
-rw-r--r--benches/benches/rasterizer.rs204
-rw-r--r--benches/main.rs9
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
+}