Skip to content

Commit

Permalink
Make benchmark setup consistent (#16733)
Browse files Browse the repository at this point in the history
# Objective

- Benchmarks are inconsistently setup, there are several that do not
compile, and several others that need to be reformatted.
- Related / precursor to #16647, this is part of my attempt migrating
[`bevy-bencher`](https://github.com/TheBevyFlock/bevy-bencher) to the
official benchmarks.

## Solution

> [!TIP]
>
> I recommend reviewing this PR commit-by-commit, instead of all at
once!

In 5d26f56 I reorganized how benches
were registered. Now this is one `[[bench]]` per Bevy crate. In each
crate benchmark folder, there is a `main.rs` that calls
`criterion_main!`. I also disabled automatic benchmark discovery, which
isn't necessarily required, but may clear up confusion with our custom
setup. I also fixed a few errors that were causing the benchmarks to
fail to compile.

In afc8d33 I ran `rustfmt` on all of
the benchmarks.

In d6cdf96 I fixed all of the Clippy
warnings.

In ee94d48 I fixed some of the
benchmarks' usage of `black_box()`. I ended up opening
rust-lang/rust#133942 due to this, which should
help prevent this in the future.

In cbe1688 I renamed all of the ECS
benchmark groups to be called `benches`, to be consistent with the other
crate benchmarks.

In e701c21 and
8815bb7 I re-ordered some imports and
module definitions, and uplifted `fragmentation/mod.rs` to
`fragementation.rs`.

Finally, in b0065e0 I organized
`Cargo.toml` and bumped Criterion to v0.5.

## Testing

- `cd benches && cargo clippy --benches`
- `cd benches && cargo fmt --all`
  • Loading branch information
BD103 authored Dec 10, 2024
1 parent c60dcea commit c4a24d5
Show file tree
Hide file tree
Showing 34 changed files with 178 additions and 185 deletions.
68 changes: 22 additions & 46 deletions benches/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@ edition = "2021"
description = "Benchmarks that test Bevy's performance"
publish = false
license = "MIT OR Apache-2.0"
# Do not automatically discover benchmarks, we specify them manually instead.
autobenches = false

[dev-dependencies]
glam = "0.29"
rand = "0.8"
rand_chacha = "0.3"
criterion = { version = "0.3", features = ["html_reports"] }
# Bevy crates
bevy_app = { path = "../crates/bevy_app" }
bevy_ecs = { path = "../crates/bevy_ecs", features = ["multi_threaded"] }
bevy_hierarchy = { path = "../crates/bevy_hierarchy" }
Expand All @@ -22,70 +21,47 @@ bevy_render = { path = "../crates/bevy_render" }
bevy_tasks = { path = "../crates/bevy_tasks" }
bevy_utils = { path = "../crates/bevy_utils" }

# make bevy_render compile on linux. x11 vs wayland does not matter here as the benches do not actually use a window
# Other crates
criterion = { version = "0.5.1", features = ["html_reports"] }
glam = "0.29"
rand = "0.8"
rand_chacha = "0.3"

# Make `bevy_render` compile on Linux with x11 windowing. x11 vs. Wayland does not matter here
# because the benches do not actually open any windows.
[target.'cfg(target_os = "linux")'.dev-dependencies]
bevy_winit = { path = "../crates/bevy_winit", features = ["x11"] }

[profile.release]
opt-level = 3
lto = true

[[bench]]
name = "change_detection"
path = "benches/bevy_ecs/change_detection.rs"
harness = false

[[bench]]
name = "ecs"
path = "benches/bevy_ecs/benches.rs"
harness = false

[[bench]]
name = "ray_mesh_intersection"
path = "benches/bevy_picking/ray_mesh_intersection.rs"
harness = false

[[bench]]
name = "reflect_function"
path = "benches/bevy_reflect/function.rs"
harness = false

[[bench]]
name = "reflect_list"
path = "benches/bevy_reflect/list.rs"
harness = false

[[bench]]
name = "reflect_map"
path = "benches/bevy_reflect/map.rs"
harness = false

[[bench]]
name = "reflect_struct"
path = "benches/bevy_reflect/struct.rs"
path = "benches/bevy_ecs/main.rs"
harness = false

[[bench]]
name = "parse_reflect_path"
path = "benches/bevy_reflect/path.rs"
name = "math"
path = "benches/bevy_math/main.rs"
harness = false

[[bench]]
name = "iter"
path = "benches/bevy_tasks/iter.rs"
name = "picking"
path = "benches/bevy_picking/main.rs"
harness = false

[[bench]]
name = "bezier"
path = "benches/bevy_math/bezier.rs"
name = "reflect"
path = "benches/bevy_reflect/main.rs"
harness = false

[[bench]]
name = "torus"
path = "benches/bevy_render/torus.rs"
name = "render"
path = "benches/bevy_render/main.rs"
harness = false

[[bench]]
name = "entity_hash"
path = "benches/bevy_ecs/world/entity_hash.rs"
name = "tasks"
path = "benches/bevy_tasks/main.rs"
harness = false
23 changes: 0 additions & 23 deletions benches/benches/bevy_ecs/benches.rs

This file was deleted.

17 changes: 9 additions & 8 deletions benches/benches/bevy_ecs/change_detection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use bevy_ecs::{
query::QueryFilter,
world::World,
};
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use criterion::{black_box, criterion_group, Criterion};
use rand::{prelude::SliceRandom, SeedableRng};
use rand_chacha::ChaCha8Rng;

Expand All @@ -17,7 +17,6 @@ criterion_group!(
none_changed_detection,
multiple_archetype_none_changed_detection
);
criterion_main!(benches);

macro_rules! modify {
($components:ident;$($index:tt),*) => {
Expand Down Expand Up @@ -96,7 +95,7 @@ fn all_added_detection_generic<T: Component + Default>(group: &mut BenchGroup, e
},
|(ref mut world, ref mut query)| {
let mut count = 0;
for entity in query.iter(&world) {
for entity in query.iter(world) {
black_box(entity);
count += 1;
}
Expand Down Expand Up @@ -144,7 +143,7 @@ fn all_changed_detection_generic<T: Component<Mutability = Mutable> + Default +
},
|(ref mut world, ref mut query)| {
let mut count = 0;
for entity in query.iter(&world) {
for entity in query.iter(world) {
black_box(entity);
count += 1;
}
Expand Down Expand Up @@ -196,7 +195,7 @@ fn few_changed_detection_generic<T: Component<Mutability = Mutable> + Default +
(world, query)
},
|(ref mut world, ref mut query)| {
for entity in query.iter(&world) {
for entity in query.iter(world) {
black_box(entity);
}
},
Expand Down Expand Up @@ -238,7 +237,7 @@ fn none_changed_detection_generic<T: Component<Mutability = Mutable> + Default>(
},
|(ref mut world, ref mut query)| {
let mut count = 0;
for entity in query.iter(&world) {
for entity in query.iter(world) {
black_box(entity);
count += 1;
}
Expand Down Expand Up @@ -298,7 +297,9 @@ fn add_archetypes_entities<T: Component<Mutability = Mutable> + Default>(
}
}
}
fn multiple_archetype_none_changed_detection_generic<T: Component<Mutability = Mutable> + Default + BenchModify>(
fn multiple_archetype_none_changed_detection_generic<
T: Component<Mutability = Mutable> + Default + BenchModify,
>(
group: &mut BenchGroup,
archetype_count: u16,
entity_count: u32,
Expand Down Expand Up @@ -342,7 +343,7 @@ fn multiple_archetype_none_changed_detection_generic<T: Component<Mutability = M
},
|(ref mut world, ref mut query)| {
let mut count = 0;
for entity in query.iter(&world) {
for entity in query.iter(world) {
black_box(entity);
count += 1;
}
Expand Down
7 changes: 3 additions & 4 deletions benches/benches/bevy_ecs/components/mod.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
use criterion::*;

mod add_remove;
mod add_remove_big_sparse_set;
mod add_remove_big_table;
mod add_remove_sparse_set;
mod add_remove_table;
mod add_remove_very_big_table;
mod add_remove;
mod archetype_updates;
mod insert_simple;
mod insert_simple_unbatched;

use archetype_updates::*;
use criterion::{criterion_group, Criterion};

criterion_group!(
components_benches,
benches,
add_remove,
add_remove_big,
add_remove_very_big,
Expand Down
31 changes: 16 additions & 15 deletions benches/benches/bevy_ecs/empty_archetypes.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use bevy_ecs::{component::Component, prelude::*, world::World};
use bevy_tasks::{ComputeTaskPool, TaskPool};
use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion};
use bevy_ecs::{component::Component, prelude::*, schedule::ExecutorKind, world::World};
use criterion::{black_box, criterion_group, BenchmarkId, Criterion};

criterion_group!(benches, empty_archetypes);
criterion_main!(benches);

#[derive(Component)]
struct A<const N: u16>(f32);
Expand Down Expand Up @@ -47,13 +45,12 @@ fn for_each(
&A<12>,
)>,
) {
query.for_each(|comp| {
query.iter().for_each(|comp| {
black_box(comp);
});
}

fn par_for_each(
task_pool: Res<ComputeTaskPool>,
query: Query<(
&A<0>,
&A<1>,
Expand All @@ -70,25 +67,29 @@ fn par_for_each(
&A<12>,
)>,
) {
query.par_for_each(&*task_pool, 64, |comp| {
query.par_iter().for_each(|comp| {
black_box(comp);
});
}

fn setup(parallel: bool, setup: impl FnOnce(&mut Schedule)) -> (World, Schedule) {
let mut world = World::new();
let world = World::new();
let mut schedule = Schedule::default();
if parallel {
world.insert_resource(ComputeTaskPool(TaskPool::default()));
}

schedule.set_executor_kind(match parallel {
true => ExecutorKind::MultiThreaded,
false => ExecutorKind::SingleThreaded,
});

setup(&mut schedule);

(world, schedule)
}

/// create `count` entities with distinct archetypes
fn add_archetypes(world: &mut World, count: u16) {
for i in 0..count {
let mut e = world.spawn();
let mut e = world.spawn_empty();
e.insert(A::<0>(1.0));
e.insert(A::<1>(1.0));
e.insert(A::<2>(1.0));
Expand Down Expand Up @@ -158,7 +159,7 @@ fn empty_archetypes(criterion: &mut Criterion) {
});
add_archetypes(&mut world, archetype_count);
world.clear_entities();
let mut e = world.spawn();
let mut e = world.spawn_empty();
e.insert(A::<0>(1.0));
e.insert(A::<1>(1.0));
e.insert(A::<2>(1.0));
Expand Down Expand Up @@ -189,7 +190,7 @@ fn empty_archetypes(criterion: &mut Criterion) {
});
add_archetypes(&mut world, archetype_count);
world.clear_entities();
let mut e = world.spawn();
let mut e = world.spawn_empty();
e.insert(A::<0>(1.0));
e.insert(A::<1>(1.0));
e.insert(A::<2>(1.0));
Expand Down Expand Up @@ -220,7 +221,7 @@ fn empty_archetypes(criterion: &mut Criterion) {
});
add_archetypes(&mut world, archetype_count);
world.clear_entities();
let mut e = world.spawn();
let mut e = world.spawn_empty();
e.insert(A::<0>(1.0));
e.insert(A::<1>(1.0));
e.insert(A::<2>(1.0));
Expand Down
6 changes: 3 additions & 3 deletions benches/benches/bevy_ecs/events/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use criterion::*;

mod iter;
mod send;

criterion_group!(event_benches, send, iter);
use criterion::{criterion_group, Criterion};

criterion_group!(benches, send, iter);

fn send(c: &mut Criterion) {
let mut group = c.benchmark_group("events_send");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use bevy_ecs::prelude::*;
use bevy_ecs::system::SystemState;
use core::hint::black_box;
use criterion::*;
use glam::*;
use core::hint::black_box;

criterion_group!(fragmentation_benches, iter_frag_empty);
criterion_group!(benches, iter_frag_empty);

#[derive(Component, Default)]
struct Table<const X: usize = 0>(usize);
Expand Down
7 changes: 3 additions & 4 deletions benches/benches/bevy_ecs/iteration/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use criterion::*;

mod heavy_compute;
mod iter_frag;
mod iter_frag_foreach;
Expand All @@ -22,10 +20,11 @@ mod iter_simple_wide_sparse_set;
mod par_iter_simple;
mod par_iter_simple_foreach_hybrid;

use criterion::{criterion_group, Criterion};
use heavy_compute::*;

criterion_group!(
iterations_benches,
benches,
iter_frag,
iter_frag_sparse,
iter_simple,
Expand Down Expand Up @@ -136,7 +135,7 @@ fn par_iter_simple(c: &mut Criterion) {
b.iter(move || bench.run());
});
}
group.bench_function(format!("hybrid"), |b| {
group.bench_function("hybrid".to_string(), |b| {
let mut bench = par_iter_simple_foreach_hybrid::Benchmark::new();
b.iter(move || bench.run());
});
Expand Down
Loading

0 comments on commit c4a24d5

Please sign in to comment.