Skip to content

Commit

Permalink
Add a random access get_component benchmark (#4607)
Browse files Browse the repository at this point in the history
# Objective

Add a benchmark to measure the performance of get_component, particularly for cases involving random access.

Enables #2965
  • Loading branch information
TheRawMeatball committed Apr 26, 2022
1 parent 4e547de commit 87991c5
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 1 deletion.
2 changes: 2 additions & 0 deletions benches/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ license = "MIT OR Apache-2.0"

[dev-dependencies]
glam = "0.20"
rand = "0.8"
rand_chacha = "0.3"
criterion = { version = "0.3", features = ["html_reports"] }
bevy_ecs = { path = "../crates/bevy_ecs" }
bevy_tasks = { path = "../crates/bevy_tasks" }
Expand Down
119 changes: 118 additions & 1 deletion benches/benches/bevy_ecs/world_get.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
use bevy_ecs::{component::Component, entity::Entity, world::World};
use bevy_ecs::{
component::Component,
entity::Entity,
system::{Query, SystemState},
world::World,
};
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use rand::{prelude::SliceRandom, SeedableRng};
use rand_chacha::ChaCha8Rng;

criterion_group!(
benches,
Expand All @@ -8,6 +15,8 @@ criterion_group!(
world_query_get,
world_query_iter,
world_query_for_each,
query_get_component,
query_get,
);
criterion_main!(benches);

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

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

fn deterministic_rand() -> ChaCha8Rng {
ChaCha8Rng::seed_from_u64(42)
}

fn setup<T: Component + Default>(entity_count: u32) -> World {
let mut world = World::default();
world.spawn_batch((0..entity_count).map(|_| (T::default(),)));
Expand Down Expand Up @@ -188,3 +201,107 @@ fn world_query_for_each(criterion: &mut Criterion) {

group.finish();
}

fn query_get_component(criterion: &mut Criterion) {
let mut group = criterion.benchmark_group("query_get_component");
group.warm_up_time(std::time::Duration::from_millis(500));
group.measurement_time(std::time::Duration::from_secs(4));

for entity_count in RANGE.map(|i| i * 10_000) {
group.bench_function(format!("{}_entities_table", entity_count), |bencher| {
let mut world = World::default();
let mut entities: Vec<_> = world
.spawn_batch((0..entity_count).map(|_| (Table::default(),)))
.collect();
entities.shuffle(&mut deterministic_rand());
let mut query = SystemState::<Query<&Table>>::new(&mut world);
let query = query.get(&world);

bencher.iter(|| {
let mut count = 0;
for comp in entities
.iter()
.flat_map(|&e| query.get_component::<Table>(e))
{
black_box(comp);
count += 1;
black_box(count);
}
assert_eq!(black_box(count), entity_count);
});
});
group.bench_function(format!("{}_entities_sparse", entity_count), |bencher| {
let mut world = World::default();
let mut entities: Vec<_> = world
.spawn_batch((0..entity_count).map(|_| (Sparse::default(),)))
.collect();
entities.shuffle(&mut deterministic_rand());
let mut query = SystemState::<Query<&Sparse>>::new(&mut world);
let query = query.get(&world);

bencher.iter(|| {
let mut count = 0;
for comp in entities
.iter()
.flat_map(|&e| query.get_component::<Sparse>(e))
{
black_box(comp);
count += 1;
black_box(count);
}
assert_eq!(black_box(count), entity_count);
});
});
}

group.finish();
}

fn query_get(criterion: &mut Criterion) {
let mut group = criterion.benchmark_group("query_get");
group.warm_up_time(std::time::Duration::from_millis(500));
group.measurement_time(std::time::Duration::from_secs(4));

for entity_count in RANGE.map(|i| i * 10_000) {
group.bench_function(format!("{}_entities_table", entity_count), |bencher| {
let mut world = World::default();
let mut entities: Vec<_> = world
.spawn_batch((0..entity_count).map(|_| (Table::default(),)))
.collect();
entities.shuffle(&mut deterministic_rand());
let mut query = SystemState::<Query<&Table>>::new(&mut world);
let query = query.get(&world);

bencher.iter(|| {
let mut count = 0;
for comp in entities.iter().flat_map(|&e| query.get(e)) {
black_box(comp);
count += 1;
black_box(count);
}
assert_eq!(black_box(count), entity_count);
});
});
group.bench_function(format!("{}_entities_sparse", entity_count), |bencher| {
let mut world = World::default();
let mut entities: Vec<_> = world
.spawn_batch((0..entity_count).map(|_| (Sparse::default(),)))
.collect();
entities.shuffle(&mut deterministic_rand());
let mut query = SystemState::<Query<&Sparse>>::new(&mut world);
let query = query.get(&world);

bencher.iter(|| {
let mut count = 0;
for comp in entities.iter().flat_map(|&e| query.get(e)) {
black_box(comp);
count += 1;
black_box(count);
}
assert_eq!(black_box(count), entity_count);
});
});
}

group.finish();
}

0 comments on commit 87991c5

Please sign in to comment.