forked from bevyengine/bevy
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Opportunistically use dense iteration for archetypal iteration (bevye…
…ngine#14049) # Objective - currently, bevy employs sparse iteration if any of the target components in the query are stored in a sparse set. it may lead to increased cache misses in some cases, potentially impacting performance. - partial fixes bevyengine#12381 ## Solution - use dense iteration when an archetype and its table have the same entity count. - to avoid introducing complicate unsafe noise, this pr only implement for `for_each ` style iteration. - added a benchmark to test performance for hybrid iteration. ## Performance ![image](https://github.com/bevyengine/bevy/assets/45868716/5cce13cf-6ff2-4861-9576-e75edc63bd46) nearly 2x win in specific scenarios, and no performance degradation in other test cases. --------- Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com> Co-authored-by: Christian Hughes <9044780+ItsDoot@users.noreply.github.com>
- Loading branch information
1 parent
7c80ae7
commit 8235daa
Showing
3 changed files
with
129 additions
and
2 deletions.
There are no files selected for viewing
43 changes: 43 additions & 0 deletions
43
benches/benches/bevy_ecs/iteration/iter_simple_foreach_hybrid.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
use bevy_ecs::prelude::*; | ||
use rand::{prelude::SliceRandom, SeedableRng}; | ||
use rand_chacha::ChaCha8Rng; | ||
|
||
#[derive(Component, Copy, Clone)] | ||
struct TableData(f32); | ||
|
||
#[derive(Component, Copy, Clone)] | ||
#[component(storage = "SparseSet")] | ||
struct SparseData(f32); | ||
|
||
fn deterministic_rand() -> ChaCha8Rng { | ||
ChaCha8Rng::seed_from_u64(42) | ||
} | ||
pub struct Benchmark<'w>(World, QueryState<(&'w mut TableData, &'w SparseData)>); | ||
|
||
impl<'w> Benchmark<'w> { | ||
pub fn new() -> Self { | ||
let mut world = World::new(); | ||
|
||
let mut v = vec![]; | ||
for _ in 0..10000 { | ||
world.spawn((TableData(0.0), SparseData(0.0))).id(); | ||
v.push(world.spawn(TableData(0.)).id()); | ||
} | ||
|
||
// by shuffling ,randomize the archetype iteration order to significantly deviate from the table order. This maximizes the loss of cache locality during archetype-based iteration. | ||
v.shuffle(&mut deterministic_rand()); | ||
for e in v.into_iter() { | ||
world.entity_mut(e).despawn(); | ||
} | ||
|
||
let query = world.query::<(&mut TableData, &SparseData)>(); | ||
Self(world, query) | ||
} | ||
|
||
#[inline(never)] | ||
pub fn run(&mut self) { | ||
self.1 | ||
.iter_mut(&mut self.0) | ||
.for_each(|(mut v1, v2)| v1.0 += v2.0) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters