diff --git a/benches/common/bezier.rs b/benches/common/bezier.rs index 441e4d6..2811622 100644 --- a/benches/common/bezier.rs +++ b/benches/common/bezier.rs @@ -1,32 +1,49 @@ use criterion::{black_box, Criterion}; +use gammalg::bezier::BezierCurve; use crate::common::samples::CURVES; +macro_rules! bench_curve_types { + ($group:ident, $body:expr) => { + $group.bench_function("linear", |b| { + for curve in CURVES.LINEAR.iter() { + b.iter(|| $body(curve)) + } + }); + $group.bench_function("quadratic", |b| { + for curve in CURVES.QUADRATIC.iter() { + b.iter(|| $body(curve)) + } + }); + $group.bench_function("cubic", |b| { + for curve in CURVES.CUBIC.iter() { + b.iter(|| $body(curve)) + } + }); + $group.bench_function("higher", |b| { + for curve in CURVES.HIGHER.iter() { + b.iter(|| $body(curve)) + } + }); + } +} + pub fn split(c: &mut Criterion) { - c.bench_function("split", |b| { - for curve in CURVES.iter() { - b.iter(|| black_box(curve.split(0.5))) - } - }); + let mut g = c.benchmark_group("BezierCurve::split"); + bench_curve_types!(g, |curve: &BezierCurve| curve.split(black_box(0.5))); } -pub fn eval(c: &mut Criterion) { - c.bench_function("eval", |b| { - for curve in CURVES.iter() { - b.iter(|| black_box(curve.castlejau_eval(0.5))) - } - }); +pub fn castlejau_eval(c: &mut Criterion) { + let mut g = c.benchmark_group("BezierCurve::castlejau_eval"); + bench_curve_types!(g, |curve: &BezierCurve| curve.castlejau_eval(black_box(0.5))); } pub fn normal(c: &mut Criterion) { - c.bench_function("normal", |b| { - for curve in CURVES.iter() { - b.iter(|| black_box(curve.normal(0.5))) - } - }); + let mut g = c.benchmark_group("BezierCurve::normal"); + bench_curve_types!(g, |curve: &BezierCurve| curve.normal(black_box(0.5))); } pub fn all(c: &mut Criterion) { split(c); - eval(c); + castlejau_eval(c); normal(c); } diff --git a/benches/common/samples.rs b/benches/common/samples.rs index 4df6349..390c81a 100644 --- a/benches/common/samples.rs +++ b/benches/common/samples.rs @@ -3,29 +3,91 @@ use smallvec::smallvec; use nalgebra::Vector2; use gammalg::bezier::BezierCurve; -pub static CURVES: Lazy>> = Lazy::new(|| vec![ - BezierCurve(smallvec![ - Vector2::new(0.0, 0.0), - Vector2::new(10.0, 0.0), - Vector2::new(0.0, 10.0), - Vector2::new(10.0, 10.0), - ]), - BezierCurve(smallvec![ - Vector2::new(50.0, 0.0), - Vector2::new(200.0, 33.0), - Vector2::new(0.0, 66.0), - Vector2::new(50.0, 100.0), - ]), - BezierCurve(smallvec![ - Vector2::new(50.0, 0.0), - Vector2::new(155.0, 23.1), - Vector2::new(88.5, 46.2), - Vector2::new(56.3, 69.643) - ]), - BezierCurve(smallvec![ - Vector2::new(56.3, 69.643), - Vector2::new(42.5, 79.69), - Vector2::new(35.0, 89.8), - Vector2::new(50.0, 100.0) - ]), -]); +/// Points generated randomly +/// ```python +/// from random import random +/// for i in range(10): +/// print(f"Vector2::new({(random()-0.5)*i}, {(random()-0.5)*i})") +/// ``` +pub static POINTS: [Vector2; 10] = [ + Vector2::new( 0.0, 0.0 ), + Vector2::new(-0.29734, 0.44984), + Vector2::new(-0.52560, 0.42885), + Vector2::new( 1.42777, -0.02652), + Vector2::new( 1.98032, -0.67824), + Vector2::new( 0.44863, -0.91328), + Vector2::new(-2.51139, -0.79100), + Vector2::new(-3.10479, -0.59318), + Vector2::new(-1.16022, -2.95591), + Vector2::new(-1.07946, 0.78888), +]; + +pub static CURVES: Lazy = Lazy::new(Curves::new); +#[allow(non_snake_case)] +pub struct Curves { + pub LINEAR: Vec>, + pub QUADRATIC: Vec>, + pub CUBIC: Vec>, + pub HIGHER: Vec>, +} +impl Curves { + pub fn new() -> Curves { + Curves { + LINEAR: vec![ + BezierCurve([0, 1].into_iter().map(|i| POINTS[i]).collect()), + BezierCurve([1, 2].into_iter().map(|i| POINTS[i]).collect()), + BezierCurve([2, 3].into_iter().map(|i| POINTS[i]).collect()), + BezierCurve([3, 4].into_iter().map(|i| POINTS[i]).collect()), + BezierCurve([4, 5].into_iter().map(|i| POINTS[i]).collect()), + BezierCurve([5, 6].into_iter().map(|i| POINTS[i]).collect()), + BezierCurve([6, 7].into_iter().map(|i| POINTS[i]).collect()), + BezierCurve([7, 8].into_iter().map(|i| POINTS[i]).collect()), + BezierCurve([8, 9].into_iter().map(|i| POINTS[i]).collect()), + BezierCurve([9, 0].into_iter().map(|i| POINTS[i]).collect()), + ], + QUADRATIC: vec![ + BezierCurve([0, 1, 2].into_iter().map(|i| POINTS[i]).collect()), + BezierCurve([2, 3, 4].into_iter().map(|i| POINTS[i]).collect()), + BezierCurve([4, 6, 8].into_iter().map(|i| POINTS[i]).collect()), + BezierCurve([1, 3, 5].into_iter().map(|i| POINTS[i]).collect()), + BezierCurve([5, 7, 9].into_iter().map(|i| POINTS[i]).collect()), + BezierCurve([0, 2, 1].into_iter().map(|i| POINTS[i]).collect()), + BezierCurve([2, 4, 3].into_iter().map(|i| POINTS[i]).collect()), + BezierCurve([4, 8, 6].into_iter().map(|i| POINTS[i]).collect()), + BezierCurve([1, 5, 3].into_iter().map(|i| POINTS[i]).collect()), + BezierCurve([5, 9, 7].into_iter().map(|i| POINTS[i]).collect()), + ], + CUBIC: vec![ + BezierCurve([0, 1, 2, 3].into_iter().map(|i| POINTS[i]).collect()), + BezierCurve([2, 3, 4, 5].into_iter().map(|i| POINTS[i]).collect()), + BezierCurve([4, 5, 6, 7].into_iter().map(|i| POINTS[i]).collect()), + BezierCurve([6, 7, 8, 9].into_iter().map(|i| POINTS[i]).collect()), + BezierCurve([8, 9, 0, 1].into_iter().map(|i| POINTS[i]).collect()), + BezierCurve([0, 4, 2, 6].into_iter().map(|i| POINTS[i]).collect()), + BezierCurve([1, 5, 3, 7].into_iter().map(|i| POINTS[i]).collect()), + BezierCurve([2, 6, 4, 8].into_iter().map(|i| POINTS[i]).collect()), + BezierCurve([3, 7, 5, 9].into_iter().map(|i| POINTS[i]).collect()), + BezierCurve([4, 8, 6, 0].into_iter().map(|i| POINTS[i]).collect()), + ], + HIGHER: vec![ + BezierCurve([0, 1, 2, 3, 4].into_iter().map(|i| POINTS[i]).collect()), + BezierCurve([2, 3, 4, 5, 6].into_iter().map(|i| POINTS[i]).collect()), + BezierCurve([4, 5, 6, 7, 8].into_iter().map(|i| POINTS[i]).collect()), + BezierCurve([6, 7, 8, 9, 0].into_iter().map(|i| POINTS[i]).collect()), + BezierCurve([8, 9, 0, 1, 2].into_iter().map(|i| POINTS[i]).collect()), + BezierCurve([0, 4, 2, 6, 8].into_iter().map(|i| POINTS[i]).collect()), + BezierCurve([1, 5, 3, 7, 9].into_iter().map(|i| POINTS[i]).collect()), + BezierCurve([2, 6, 4, 8, 0].into_iter().map(|i| POINTS[i]).collect()), + BezierCurve([3, 7, 5, 9, 1].into_iter().map(|i| POINTS[i]).collect()), + BezierCurve([4, 8, 6, 0, 2].into_iter().map(|i| POINTS[i]).collect()), + ], + } + } + + pub fn iter(&self) -> impl Iterator> { + self.LINEAR.iter() + .chain(self.QUADRATIC.iter()) + .chain(self.CUBIC.iter()) + .chain(self.HIGHER.iter()) + } +} diff --git a/benches/flamegraph.rs b/benches/flamegraph.rs index 17d4132..1e67a35 100644 --- a/benches/flamegraph.rs +++ b/benches/flamegraph.rs @@ -1,10 +1,14 @@ +use std::time::Duration; use criterion::{criterion_group, criterion_main, Criterion}; use pprof::criterion::{PProfProfiler, Output}; mod common; +static SECOND: Duration = Duration::from_secs(1); criterion_group!{ name = benches; - config = Criterion::default().with_profiler(PProfProfiler::new(100, Output::Flamegraph(None))); + config = Criterion::default() + .with_profiler(PProfProfiler::new(100, Output::Flamegraph(None))) + ; targets = common::bezier::all } criterion_main!(benches); \ No newline at end of file diff --git a/benches/speed.rs b/benches/speed.rs index 697b523..5777a67 100644 --- a/benches/speed.rs +++ b/benches/speed.rs @@ -1,9 +1,14 @@ +use std::time::Duration; use criterion::{criterion_group, criterion_main, Criterion}; mod common; +static SECOND: Duration = Duration::from_secs(1); criterion_group!{ name = benches; - config = Criterion::default(); + config = Criterion::default() + .warm_up_time(SECOND) + .measurement_time(SECOND) + ; targets = common::bezier::all } criterion_main!(benches);