Skip to content

Commit

Permalink
feat: overhaul bezier curve benchmarks
Browse files Browse the repository at this point in the history
- Apply `bench!` macro to all names
- Rename benchmarks to be more descriptive of what they do
- Deduplicate `build_pos_cubic()` and `build_accel_cubic()`, since they both benchmark the exact same thing!
- Move calculation of time for curve easing outside main routine
- Move `curve.position()` benchmarks under the same group, and make their routine generic
- Remove unnecessary `Vec` allocation from `build_pos_cubic()`
  • Loading branch information
BD103 committed Dec 29, 2024
1 parent 64efd08 commit 2f1095b
Showing 1 changed file with 62 additions and 57 deletions.
119 changes: 62 additions & 57 deletions benches/benches/bevy_math/bezier.rs
Original file line number Diff line number Diff line change
@@ -1,94 +1,99 @@
use criterion::{black_box, criterion_group, Criterion};
use benches::bench;
use bevy_math::{prelude::*, VectorSpace};
use criterion::{
black_box, criterion_group, measurement::Measurement, BatchSize, BenchmarkGroup, BenchmarkId,
Criterion,
};

use bevy_math::prelude::*;
criterion_group!(benches, segment_ease, curve_position, curve_iter_positions);

fn easing(c: &mut Criterion) {
let cubic_bezier = CubicSegment::new_bezier(vec2(0.25, 0.1), vec2(0.25, 1.0));
c.bench_function("easing_1000", |b| {
b.iter(|| {
(0..1000).map(|i| i as f32 / 1000.0).for_each(|t| {
black_box(cubic_bezier.ease(black_box(t)));
});
});
fn segment_ease(c: &mut Criterion) {
let segment = black_box(CubicSegment::new_bezier(vec2(0.25, 0.1), vec2(0.25, 1.0)));

c.bench_function(bench!("segment_ease"), |b| {
let mut t = 0;

b.iter_batched(
|| {
// Increment `t` by 1, but use modulo to constrain it to `0..=1000`.
t = (t + 1) % 1001;

// Return time as a decimal between 0 and 1, inclusive.
t as f32 / 1000.0
},
|t| segment.ease(t),
BatchSize::SmallInput,
);
});
}

fn cubic_2d(c: &mut Criterion) {
let bezier = CubicBezier::new([[
fn curve_position(c: &mut Criterion) {
/// A helper function that benchmarks calling [`CubicCurve::position()`] over a generic [`VectorSpace`].
fn bench_curve<M: Measurement, P: VectorSpace>(
group: &mut BenchmarkGroup<M>,
name: &str,
curve: CubicCurve<P>,
) {
group.bench_with_input(BenchmarkId::from_parameter(name), &curve, |b, curve| {
b.iter(|| curve.position(black_box(0.5)));
});
}

let mut group = c.benchmark_group(bench!("curve_position"));

let bezier_2 = CubicBezier::new([[
vec2(0.0, 0.0),
vec2(0.0, 1.0),
vec2(1.0, 0.0),
vec2(1.0, 1.0),
]])
.to_curve()
.expect("Unable to build a curve from this data");
c.bench_function("cubic_position_Vec2", |b| {
b.iter(|| black_box(bezier.position(black_box(0.5))));
});
}
.unwrap();

fn cubic(c: &mut Criterion) {
let bezier = CubicBezier::new([[
vec3a(0.0, 0.0, 0.0),
vec3a(0.0, 1.0, 0.0),
vec3a(1.0, 0.0, 0.0),
vec3a(1.0, 1.0, 1.0),
]])
.to_curve()
.expect("Unable to build a curve from this data");
c.bench_function("cubic_position_Vec3A", |b| {
b.iter(|| black_box(bezier.position(black_box(0.5))));
});
}
bench_curve(&mut group, "vec2", bezier_2);

fn cubic_vec3(c: &mut Criterion) {
let bezier = CubicBezier::new([[
let bezier_3 = CubicBezier::new([[
vec3(0.0, 0.0, 0.0),
vec3(0.0, 1.0, 0.0),
vec3(1.0, 0.0, 0.0),
vec3(1.0, 1.0, 1.0),
]])
.to_curve()
.expect("Unable to build a curve from this data");
c.bench_function("cubic_position_Vec3", |b| {
b.iter(|| black_box(bezier.position(black_box(0.5))));
});
}
.unwrap();

fn build_pos_cubic(c: &mut Criterion) {
let bezier = CubicBezier::new([[
bench_curve(&mut group, "vec3", bezier_3);

let bezier_3a = CubicBezier::new([[
vec3a(0.0, 0.0, 0.0),
vec3a(0.0, 1.0, 0.0),
vec3a(1.0, 0.0, 0.0),
vec3a(1.0, 1.0, 1.0),
]])
.to_curve()
.expect("Unable to build a curve from this data");
c.bench_function("build_pos_cubic_100_points", |b| {
b.iter(|| black_box(bezier.iter_positions(black_box(100)).collect::<Vec<_>>()));
});
.unwrap();

bench_curve(&mut group, "vec3a", bezier_3a);

group.finish();
}

fn build_accel_cubic(c: &mut Criterion) {
fn curve_iter_positions(c: &mut Criterion) {
let bezier = CubicBezier::new([[
vec3a(0.0, 0.0, 0.0),
vec3a(0.0, 1.0, 0.0),
vec3a(1.0, 0.0, 0.0),
vec3a(1.0, 1.0, 1.0),
]])
.to_curve()
.expect("Unable to build a curve from this data");
c.bench_function("build_accel_cubic_100_points", |b| {
b.iter(|| black_box(bezier.iter_positions(black_box(100)).collect::<Vec<_>>()));
.unwrap();

c.bench_function(bench!("curve_iter_positions"), |b| {
b.iter(|| {
for x in bezier.iter_positions(black_box(100)) {
// Discard `x`, since we just care about `iter_positions()` being consumed, but make
// the compiler believe `x` is being used so it doesn't eliminate the iterator.
black_box(x);
}
});
});
}

criterion_group!(
benches,
easing,
cubic_2d,
cubic_vec3,
cubic,
build_pos_cubic,
build_accel_cubic,
);

0 comments on commit 2f1095b

Please sign in to comment.