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
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"
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
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
Loading