Skip to content

Commit fcca6ec

Browse files
TheRawMeatballexjam
authored andcommitted
Add a random access get_component benchmark (bevyengine#4607)
# Objective Add a benchmark to measure the performance of get_component, particularly for cases involving random access. Enables bevyengine#2965
1 parent 3ec9058 commit fcca6ec

File tree

2 files changed

+120
-1
lines changed

2 files changed

+120
-1
lines changed

benches/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ license = "MIT OR Apache-2.0"
88

99
[dev-dependencies]
1010
glam = "0.20"
11+
rand = "0.8"
12+
rand_chacha = "0.3"
1113
criterion = { version = "0.3", features = ["html_reports"] }
1214
bevy_ecs = { path = "../crates/bevy_ecs" }
1315
bevy_tasks = { path = "../crates/bevy_tasks" }

benches/benches/bevy_ecs/world_get.rs

Lines changed: 118 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
1-
use bevy_ecs::{component::Component, entity::Entity, world::World};
1+
use bevy_ecs::{
2+
component::Component,
3+
entity::Entity,
4+
system::{Query, SystemState},
5+
world::World,
6+
};
27
use criterion::{black_box, criterion_group, criterion_main, Criterion};
8+
use rand::{prelude::SliceRandom, SeedableRng};
9+
use rand_chacha::ChaCha8Rng;
310

411
criterion_group!(
512
benches,
@@ -8,6 +15,8 @@ criterion_group!(
815
world_query_get,
916
world_query_iter,
1017
world_query_for_each,
18+
query_get_component,
19+
query_get,
1120
);
1221
criterion_main!(benches);
1322

@@ -20,6 +29,10 @@ struct Sparse(f32);
2029

2130
const RANGE: std::ops::Range<u32> = 5..6;
2231

32+
fn deterministic_rand() -> ChaCha8Rng {
33+
ChaCha8Rng::seed_from_u64(42)
34+
}
35+
2336
fn setup<T: Component + Default>(entity_count: u32) -> World {
2437
let mut world = World::default();
2538
world.spawn_batch((0..entity_count).map(|_| (T::default(),)));
@@ -188,3 +201,107 @@ fn world_query_for_each(criterion: &mut Criterion) {
188201

189202
group.finish();
190203
}
204+
205+
fn query_get_component(criterion: &mut Criterion) {
206+
let mut group = criterion.benchmark_group("query_get_component");
207+
group.warm_up_time(std::time::Duration::from_millis(500));
208+
group.measurement_time(std::time::Duration::from_secs(4));
209+
210+
for entity_count in RANGE.map(|i| i * 10_000) {
211+
group.bench_function(format!("{}_entities_table", entity_count), |bencher| {
212+
let mut world = World::default();
213+
let mut entities: Vec<_> = world
214+
.spawn_batch((0..entity_count).map(|_| (Table::default(),)))
215+
.collect();
216+
entities.shuffle(&mut deterministic_rand());
217+
let mut query = SystemState::<Query<&Table>>::new(&mut world);
218+
let query = query.get(&world);
219+
220+
bencher.iter(|| {
221+
let mut count = 0;
222+
for comp in entities
223+
.iter()
224+
.flat_map(|&e| query.get_component::<Table>(e))
225+
{
226+
black_box(comp);
227+
count += 1;
228+
black_box(count);
229+
}
230+
assert_eq!(black_box(count), entity_count);
231+
});
232+
});
233+
group.bench_function(format!("{}_entities_sparse", entity_count), |bencher| {
234+
let mut world = World::default();
235+
let mut entities: Vec<_> = world
236+
.spawn_batch((0..entity_count).map(|_| (Sparse::default(),)))
237+
.collect();
238+
entities.shuffle(&mut deterministic_rand());
239+
let mut query = SystemState::<Query<&Sparse>>::new(&mut world);
240+
let query = query.get(&world);
241+
242+
bencher.iter(|| {
243+
let mut count = 0;
244+
for comp in entities
245+
.iter()
246+
.flat_map(|&e| query.get_component::<Sparse>(e))
247+
{
248+
black_box(comp);
249+
count += 1;
250+
black_box(count);
251+
}
252+
assert_eq!(black_box(count), entity_count);
253+
});
254+
});
255+
}
256+
257+
group.finish();
258+
}
259+
260+
fn query_get(criterion: &mut Criterion) {
261+
let mut group = criterion.benchmark_group("query_get");
262+
group.warm_up_time(std::time::Duration::from_millis(500));
263+
group.measurement_time(std::time::Duration::from_secs(4));
264+
265+
for entity_count in RANGE.map(|i| i * 10_000) {
266+
group.bench_function(format!("{}_entities_table", entity_count), |bencher| {
267+
let mut world = World::default();
268+
let mut entities: Vec<_> = world
269+
.spawn_batch((0..entity_count).map(|_| (Table::default(),)))
270+
.collect();
271+
entities.shuffle(&mut deterministic_rand());
272+
let mut query = SystemState::<Query<&Table>>::new(&mut world);
273+
let query = query.get(&world);
274+
275+
bencher.iter(|| {
276+
let mut count = 0;
277+
for comp in entities.iter().flat_map(|&e| query.get(e)) {
278+
black_box(comp);
279+
count += 1;
280+
black_box(count);
281+
}
282+
assert_eq!(black_box(count), entity_count);
283+
});
284+
});
285+
group.bench_function(format!("{}_entities_sparse", entity_count), |bencher| {
286+
let mut world = World::default();
287+
let mut entities: Vec<_> = world
288+
.spawn_batch((0..entity_count).map(|_| (Sparse::default(),)))
289+
.collect();
290+
entities.shuffle(&mut deterministic_rand());
291+
let mut query = SystemState::<Query<&Sparse>>::new(&mut world);
292+
let query = query.get(&world);
293+
294+
bencher.iter(|| {
295+
let mut count = 0;
296+
for comp in entities.iter().flat_map(|&e| query.get(e)) {
297+
black_box(comp);
298+
count += 1;
299+
black_box(count);
300+
}
301+
assert_eq!(black_box(count), entity_count);
302+
});
303+
});
304+
}
305+
306+
group.finish();
307+
}

0 commit comments

Comments
 (0)