Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make benchmark setup consistent #16733

Merged
merged 10 commits into from
Dec 10, 2024
54 changes: 13 additions & 41 deletions benches/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ 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"
Expand All @@ -30,62 +32,32 @@ bevy_winit = { path = "../crates/bevy_winit", features = ["x11"] }
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"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was previously running function-reflection-specific benches like:

cargo bench --bench reflect_function --all-features

Does this change mean I won't be able to run specific sets of benches anymore?

Copy link
Member Author

@BD103 BD103 Dec 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but only temporarily! Just like unit tests, you can filter what subset of benchmarks you want to run:

# Will run `typed/function`, `typed/closure`, `typed/closure_mut`, and more.
cargo bench --bench reflect -- typed

My plan with #16647 is to rename all benchmarks to include their module paths, so you'll be able to run:

# This is equivalent to `cargo bench --bench reflect_function`, using the new system.
cargo bench --bench reflect -- bevy_reflect::function

This PR was a precursor, since I didn't want to have too many changes at once.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want to second this, because when I still was putting the stress test , it was very annoying to test just the bench while not testing everything else. Can you still run specific benchmarks (or groups of them) with this reorganization?

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
15 changes: 7 additions & 8 deletions benches/benches/bevy_ecs/change_detection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,18 @@ 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;

criterion_group!(
benches,
change_detection_benches,
all_added_detection,
all_changed_detection,
few_changed_detection,
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 @@ -342,7 +341,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
2 changes: 1 addition & 1 deletion benches/benches/bevy_ecs/components/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
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;
Expand Down
28 changes: 13 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 criterion::{black_box, criterion_group, BenchmarkId, Criterion};

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

#[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,26 @@ fn par_for_each(
&A<12>,
)>,
) {
query.par_for_each(&*task_pool, 64, |comp| {
query.par_iter().for_each(|comp| {
black_box(comp);
});
}

#[expect(
unused_variables,
reason = "`parallel` has no effect, it needs to be removed or parallel support needs to be re-added."
)]
fn setup(parallel: bool, setup: impl FnOnce(&mut Schedule)) -> (World, Schedule) {
BD103 marked this conversation as resolved.
Show resolved Hide resolved
let mut world = World::new();
let world = World::new();
let mut schedule = Schedule::default();
if parallel {
world.insert_resource(ComputeTaskPool(TaskPool::default()));
}
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 +156,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 +187,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 +218,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
2 changes: 1 addition & 1 deletion benches/benches/bevy_ecs/fragmentation/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
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);

Expand Down
2 changes: 1 addition & 1 deletion benches/benches/bevy_ecs/iteration/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,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
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
#![expect(dead_code, reason = "Many fields are unused/unread as they are just for benchmarking purposes.")]
#![expect(
dead_code,
reason = "Many fields are unused/unread as they are just for benchmarking purposes."
)]
#![expect(clippy::type_complexity)]

use criterion::criterion_main;

mod change_detection;
mod components;
mod empty_archetypes;
mod events;
mod fragmentation;
mod iteration;
Expand All @@ -12,7 +18,9 @@ mod scheduling;
mod world;

criterion_main!(
change_detection::change_detection_benches,
components::components_benches,
empty_archetypes::empty_archetypes_benches,
events::event_benches,
iteration::iterations_benches,
fragmentation::fragmentation_benches,
Expand Down
8 changes: 4 additions & 4 deletions benches/benches/bevy_ecs/observers/propagation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ impl<const N: usize> Event for TestEvent<N> {
const AUTO_PROPAGATE: bool = true;
}

fn send_events<const N: usize, const N_EVENTS: usize>(world: &mut World, leaves: &Vec<Entity>) {
fn send_events<const N: usize, const N_EVENTS: usize>(world: &mut World, leaves: &[Entity]) {
let target = leaves.iter().choose(&mut rand::thread_rng()).unwrap();

(0..N_EVENTS).for_each(|_| {
Expand Down Expand Up @@ -100,9 +100,9 @@ fn spawn_listener_hierarchy(world: &mut World) -> (Vec<Entity>, Vec<Entity>, Vec
}

fn add_listeners_to_hierarchy<const DENSITY: usize, const N: usize>(
roots: &Vec<Entity>,
leaves: &Vec<Entity>,
nodes: &Vec<Entity>,
roots: &[Entity],
leaves: &[Entity],
nodes: &[Entity],
world: &mut World,
) {
for e in roots.iter() {
Expand Down
8 changes: 4 additions & 4 deletions benches/benches/bevy_ecs/scheduling/run_condition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub fn run_condition_yes(criterion: &mut Criterion) {
}
// run once to initialize systems
schedule.run(&mut world);
group.bench_function(&format!("{:03}_systems", 5 * amount + 1), |bencher| {
group.bench_function(format!("{:03}_systems", 5 * amount + 1), |bencher| {
bencher.iter(|| {
schedule.run(&mut world);
});
Expand All @@ -48,7 +48,7 @@ pub fn run_condition_no(criterion: &mut Criterion) {
}
// run once to initialize systems
schedule.run(&mut world);
group.bench_function(&format!("{:03}_systems", 5 * amount + 1), |bencher| {
group.bench_function(format!("{:03}_systems", 5 * amount + 1), |bencher| {
bencher.iter(|| {
schedule.run(&mut world);
});
Expand Down Expand Up @@ -80,7 +80,7 @@ pub fn run_condition_yes_with_query(criterion: &mut Criterion) {
}
// run once to initialize systems
schedule.run(&mut world);
group.bench_function(&format!("{:03}_systems", 5 * amount + 1), |bencher| {
group.bench_function(format!("{:03}_systems", 5 * amount + 1), |bencher| {
bencher.iter(|| {
schedule.run(&mut world);
});
Expand Down Expand Up @@ -109,7 +109,7 @@ pub fn run_condition_yes_with_resource(criterion: &mut Criterion) {
}
// run once to initialize systems
schedule.run(&mut world);
group.bench_function(&format!("{:03}_systems", 5 * amount + 1), |bencher| {
group.bench_function(format!("{:03}_systems", 5 * amount + 1), |bencher| {
bencher.iter(|| {
schedule.run(&mut world);
});
Expand Down
8 changes: 4 additions & 4 deletions benches/benches/bevy_ecs/scheduling/running_systems.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pub fn empty_systems(criterion: &mut Criterion) {
schedule.add_systems(empty);
}
schedule.run(&mut world);
group.bench_function(&format!("{:03}_systems", amount), |bencher| {
group.bench_function(format!("{:03}_systems", amount), |bencher| {
bencher.iter(|| {
schedule.run(&mut world);
});
Expand All @@ -38,7 +38,7 @@ pub fn empty_systems(criterion: &mut Criterion) {
schedule.add_systems((empty, empty, empty, empty, empty));
}
schedule.run(&mut world);
group.bench_function(&format!("{:03}_systems", 5 * amount), |bencher| {
group.bench_function(format!("{:03}_systems", 5 * amount), |bencher| {
bencher.iter(|| {
schedule.run(&mut world);
});
Expand Down Expand Up @@ -80,7 +80,7 @@ pub fn busy_systems(criterion: &mut Criterion) {
}
schedule.run(&mut world);
group.bench_function(
&format!(
format!(
"{:02}x_entities_{:02}_systems",
entity_bunches,
3 * system_amount + 3
Expand Down Expand Up @@ -131,7 +131,7 @@ pub fn contrived(criterion: &mut Criterion) {
}
schedule.run(&mut world);
group.bench_function(
&format!(
format!(
"{:02}x_entities_{:02}_systems",
entity_bunches,
3 * system_amount + 3
Expand Down
2 changes: 1 addition & 1 deletion benches/benches/bevy_ecs/scheduling/schedule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ pub fn build_schedule(criterion: &mut Criterion) {
// Method: generate a set of `graph_size` systems which have a One True Ordering.
// Add system to the schedule with full constraints. Hopefully this should be maximally
// difficult for bevy to figure out.
let labels: Vec<_> = (0..1000).map(|i| NumSet(i)).collect();
let labels: Vec<_> = (0..1000).map(NumSet).collect();

// Benchmark graphs of different sizes.
for graph_size in [100, 500, 1000] {
Expand Down
Loading
Loading