From 3f26bc9f9bb6b2c6bb08694552dc9596c4daedad Mon Sep 17 00:00:00 2001 From: Elliott Pierce Date: Wed, 21 Jan 2026 22:00:56 -0500 Subject: [PATCH 1/2] add new benches --- .../bevy_ecs/world/entity_allocator.rs | 129 ++++++++++++++++++ benches/benches/bevy_ecs/world/mod.rs | 3 + 2 files changed, 132 insertions(+) create mode 100644 benches/benches/bevy_ecs/world/entity_allocator.rs diff --git a/benches/benches/bevy_ecs/world/entity_allocator.rs b/benches/benches/bevy_ecs/world/entity_allocator.rs new file mode 100644 index 0000000000000..69ba90af43989 --- /dev/null +++ b/benches/benches/bevy_ecs/world/entity_allocator.rs @@ -0,0 +1,129 @@ +use core::hint::black_box; + +use bevy_ecs::prelude::*; +use criterion::{BatchSize, Criterion}; + +pub fn entity_allocator_benches(criterion: &mut Criterion) { + let mut group = criterion.benchmark_group("entity_allocator_allocate_fresh"); + group.warm_up_time(core::time::Duration::from_millis(500)); + group.measurement_time(core::time::Duration::from_secs(4)); + + for entity_count in [1, 100, 10_000] { + group.bench_function(format!("{entity_count}_entities"), |bencher| { + bencher.iter_batched_ref( + World::default, + |world| { + for _ in 0..entity_count { + let entity = world.entity_allocator().alloc(); + black_box(entity); + } + }, + BatchSize::SmallInput, + ); + }); + } + + group.finish(); + + let mut group = criterion.benchmark_group("entity_allocator_allocate_fresh_bulk"); + group.warm_up_time(core::time::Duration::from_millis(500)); + group.measurement_time(core::time::Duration::from_secs(4)); + + for entity_count in [1, 100, 10_000] { + group.bench_function(format!("{entity_count}_entities"), |bencher| { + bencher.iter_batched_ref( + World::default, + |world| { + for entity in world.entity_allocator().alloc_many(entity_count) { + black_box(entity); + } + }, + BatchSize::SmallInput, + ); + }); + } + + group.finish(); + + let mut group = criterion.benchmark_group("entity_allocator_free"); + group.warm_up_time(core::time::Duration::from_millis(500)); + group.measurement_time(core::time::Duration::from_secs(4)); + + for entity_count in [1, 100, 10_000] { + group.bench_function(format!("{entity_count}_entities"), |bencher| { + bencher.iter_batched_ref( + || { + let world = World::new(); + let entities = + Vec::from_iter(world.entity_allocator().alloc_many(entity_count)); + (world, entities) + }, + |(world, entities)| { + entities + .drain(..) + .for_each(|e| world.entity_allocator_mut().free(e)); + }, + BatchSize::SmallInput, + ); + }); + } + + group.finish(); + + let mut group = criterion.benchmark_group("entity_allocator_allocate_reused"); + group.warm_up_time(core::time::Duration::from_millis(500)); + group.measurement_time(core::time::Duration::from_secs(4)); + + for entity_count in [1, 100, 10_000] { + group.bench_function(format!("{entity_count}_entities"), |bencher| { + bencher.iter_batched_ref( + || { + let mut world = World::new(); + let mut entities = + Vec::from_iter(world.entity_allocator().alloc_many(entity_count)); + entities + .drain(..) + .for_each(|e| world.entity_allocator_mut().free(e)); + world + }, + |world| { + for _ in 0..entity_count { + let entity = world.entity_allocator().alloc(); + black_box(entity); + } + }, + BatchSize::SmallInput, + ); + }); + } + + group.finish(); + + let mut group = criterion.benchmark_group("entity_allocator_allocate_reused_bulk"); + group.warm_up_time(core::time::Duration::from_millis(500)); + group.measurement_time(core::time::Duration::from_secs(4)); + + for entity_count in [1, 100, 10_000] { + group.bench_function(format!("{entity_count}_entities"), |bencher| { + bencher.iter_batched_ref( + || { + let mut world = World::new(); + let mut entities = + Vec::from_iter(world.entity_allocator().alloc_many(entity_count)); + entities + .drain(..) + .for_each(|e| world.entity_allocator_mut().free(e)); + world + }, + |world| { + for entity in world.entity_allocator().alloc_many(entity_count) { + black_box(entity); + } + }, + BatchSize::SmallInput, + ); + }); + } + + group.finish(); +} diff --git a/benches/benches/bevy_ecs/world/mod.rs b/benches/benches/bevy_ecs/world/mod.rs index 76a7f6aba00d3..d245c5ae4f433 100644 --- a/benches/benches/bevy_ecs/world/mod.rs +++ b/benches/benches/bevy_ecs/world/mod.rs @@ -1,6 +1,7 @@ mod commands; mod despawn; mod despawn_recursive; +mod entity_allocator; mod entity_hash; mod spawn; mod world_get; @@ -9,6 +10,7 @@ use commands::*; use criterion::criterion_group; use despawn::*; use despawn_recursive::*; +use entity_allocator::*; use entity_hash::*; use spawn::*; use world_get::*; @@ -40,4 +42,5 @@ criterion_group!( query_get_components_mut_5, query_get_components_mut_10, entity_set_build_and_lookup, + entity_allocator_benches, ); From 2c8a8115bae431ab796c6dc3243a153c4f306077 Mon Sep 17 00:00:00 2001 From: Elliott Pierce Date: Wed, 21 Jan 2026 22:07:10 -0500 Subject: [PATCH 2/2] extracted constant --- benches/benches/bevy_ecs/world/entity_allocator.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/benches/benches/bevy_ecs/world/entity_allocator.rs b/benches/benches/bevy_ecs/world/entity_allocator.rs index 69ba90af43989..c954139d9a7f1 100644 --- a/benches/benches/bevy_ecs/world/entity_allocator.rs +++ b/benches/benches/bevy_ecs/world/entity_allocator.rs @@ -4,11 +4,13 @@ use bevy_ecs::prelude::*; use criterion::{BatchSize, Criterion}; pub fn entity_allocator_benches(criterion: &mut Criterion) { + const ENTITY_COUNTS: [u32; 3] = [1, 100, 10_000]; + let mut group = criterion.benchmark_group("entity_allocator_allocate_fresh"); group.warm_up_time(core::time::Duration::from_millis(500)); group.measurement_time(core::time::Duration::from_secs(4)); - for entity_count in [1, 100, 10_000] { + for entity_count in ENTITY_COUNTS { group.bench_function(format!("{entity_count}_entities"), |bencher| { bencher.iter_batched_ref( World::default, @@ -29,7 +31,7 @@ pub fn entity_allocator_benches(criterion: &mut Criterion) { group.warm_up_time(core::time::Duration::from_millis(500)); group.measurement_time(core::time::Duration::from_secs(4)); - for entity_count in [1, 100, 10_000] { + for entity_count in ENTITY_COUNTS { group.bench_function(format!("{entity_count}_entities"), |bencher| { bencher.iter_batched_ref( World::default, @@ -49,7 +51,7 @@ pub fn entity_allocator_benches(criterion: &mut Criterion) { group.warm_up_time(core::time::Duration::from_millis(500)); group.measurement_time(core::time::Duration::from_secs(4)); - for entity_count in [1, 100, 10_000] { + for entity_count in ENTITY_COUNTS { group.bench_function(format!("{entity_count}_entities"), |bencher| { bencher.iter_batched_ref( || { @@ -74,7 +76,7 @@ pub fn entity_allocator_benches(criterion: &mut Criterion) { group.warm_up_time(core::time::Duration::from_millis(500)); group.measurement_time(core::time::Duration::from_secs(4)); - for entity_count in [1, 100, 10_000] { + for entity_count in ENTITY_COUNTS { group.bench_function(format!("{entity_count}_entities"), |bencher| { bencher.iter_batched_ref( || { @@ -103,7 +105,7 @@ pub fn entity_allocator_benches(criterion: &mut Criterion) { group.warm_up_time(core::time::Duration::from_millis(500)); group.measurement_time(core::time::Duration::from_secs(4)); - for entity_count in [1, 100, 10_000] { + for entity_count in ENTITY_COUNTS { group.bench_function(format!("{entity_count}_entities"), |bencher| { bencher.iter_batched_ref( || {