Skip to content

Commit bb78bbf

Browse files
Add benchmarks for raw entity allocation (#22640)
# Objective As per [this](#18670 (comment)) comment on #18670, this adds benchmarks for direct access to the entity allocator. ## Solution Add 5 groups of benchmarks: - allocating fresh entities - allocating fresh entities in bulk - freeing entities - allocating reused entities - allocating reused entities in bulk ## Testing - CI and benches
1 parent cf8f9be commit bb78bbf

File tree

2 files changed

+134
-0
lines changed

2 files changed

+134
-0
lines changed
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
use core::hint::black_box;
2+
3+
use bevy_ecs::prelude::*;
4+
use criterion::{BatchSize, Criterion};
5+
6+
pub fn entity_allocator_benches(criterion: &mut Criterion) {
7+
const ENTITY_COUNTS: [u32; 3] = [1, 100, 10_000];
8+
9+
let mut group = criterion.benchmark_group("entity_allocator_allocate_fresh");
10+
group.warm_up_time(core::time::Duration::from_millis(500));
11+
group.measurement_time(core::time::Duration::from_secs(4));
12+
13+
for entity_count in ENTITY_COUNTS {
14+
group.bench_function(format!("{entity_count}_entities"), |bencher| {
15+
bencher.iter_batched_ref(
16+
World::default,
17+
|world| {
18+
for _ in 0..entity_count {
19+
let entity = world.entity_allocator().alloc();
20+
black_box(entity);
21+
}
22+
},
23+
BatchSize::SmallInput,
24+
);
25+
});
26+
}
27+
28+
group.finish();
29+
30+
let mut group = criterion.benchmark_group("entity_allocator_allocate_fresh_bulk");
31+
group.warm_up_time(core::time::Duration::from_millis(500));
32+
group.measurement_time(core::time::Duration::from_secs(4));
33+
34+
for entity_count in ENTITY_COUNTS {
35+
group.bench_function(format!("{entity_count}_entities"), |bencher| {
36+
bencher.iter_batched_ref(
37+
World::default,
38+
|world| {
39+
for entity in world.entity_allocator().alloc_many(entity_count) {
40+
black_box(entity);
41+
}
42+
},
43+
BatchSize::SmallInput,
44+
);
45+
});
46+
}
47+
48+
group.finish();
49+
50+
let mut group = criterion.benchmark_group("entity_allocator_free");
51+
group.warm_up_time(core::time::Duration::from_millis(500));
52+
group.measurement_time(core::time::Duration::from_secs(4));
53+
54+
for entity_count in ENTITY_COUNTS {
55+
group.bench_function(format!("{entity_count}_entities"), |bencher| {
56+
bencher.iter_batched_ref(
57+
|| {
58+
let world = World::new();
59+
let entities =
60+
Vec::from_iter(world.entity_allocator().alloc_many(entity_count));
61+
(world, entities)
62+
},
63+
|(world, entities)| {
64+
entities
65+
.drain(..)
66+
.for_each(|e| world.entity_allocator_mut().free(e));
67+
},
68+
BatchSize::SmallInput,
69+
);
70+
});
71+
}
72+
73+
group.finish();
74+
75+
let mut group = criterion.benchmark_group("entity_allocator_allocate_reused");
76+
group.warm_up_time(core::time::Duration::from_millis(500));
77+
group.measurement_time(core::time::Duration::from_secs(4));
78+
79+
for entity_count in ENTITY_COUNTS {
80+
group.bench_function(format!("{entity_count}_entities"), |bencher| {
81+
bencher.iter_batched_ref(
82+
|| {
83+
let mut world = World::new();
84+
let mut entities =
85+
Vec::from_iter(world.entity_allocator().alloc_many(entity_count));
86+
entities
87+
.drain(..)
88+
.for_each(|e| world.entity_allocator_mut().free(e));
89+
world
90+
},
91+
|world| {
92+
for _ in 0..entity_count {
93+
let entity = world.entity_allocator().alloc();
94+
black_box(entity);
95+
}
96+
},
97+
BatchSize::SmallInput,
98+
);
99+
});
100+
}
101+
102+
group.finish();
103+
104+
let mut group = criterion.benchmark_group("entity_allocator_allocate_reused_bulk");
105+
group.warm_up_time(core::time::Duration::from_millis(500));
106+
group.measurement_time(core::time::Duration::from_secs(4));
107+
108+
for entity_count in ENTITY_COUNTS {
109+
group.bench_function(format!("{entity_count}_entities"), |bencher| {
110+
bencher.iter_batched_ref(
111+
|| {
112+
let mut world = World::new();
113+
let mut entities =
114+
Vec::from_iter(world.entity_allocator().alloc_many(entity_count));
115+
entities
116+
.drain(..)
117+
.for_each(|e| world.entity_allocator_mut().free(e));
118+
world
119+
},
120+
|world| {
121+
for entity in world.entity_allocator().alloc_many(entity_count) {
122+
black_box(entity);
123+
}
124+
},
125+
BatchSize::SmallInput,
126+
);
127+
});
128+
}
129+
130+
group.finish();
131+
}

benches/benches/bevy_ecs/world/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
mod commands;
22
mod despawn;
33
mod despawn_recursive;
4+
mod entity_allocator;
45
mod entity_hash;
56
mod spawn;
67
mod world_get;
@@ -9,6 +10,7 @@ use commands::*;
910
use criterion::criterion_group;
1011
use despawn::*;
1112
use despawn_recursive::*;
13+
use entity_allocator::*;
1214
use entity_hash::*;
1315
use spawn::*;
1416
use world_get::*;
@@ -41,4 +43,5 @@ criterion_group!(
4143
query_get_components_mut_10,
4244
query_get_components_mut_32,
4345
entity_set_build_and_lookup,
46+
entity_allocator_benches,
4447
);

0 commit comments

Comments
 (0)