mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
Optimize observer unregistration (#15150)
# Objective
Fixes #14980
## Solution
Only iterate over archetypes containing the component.
## Alternatives
Additionally, for each archetype, cache how many observers are watching
one of its components & use this to speed up the check for each affected
archetype ([implemented
here](55c89aa033
)).
Benchmarking showed this to lead only to a minor speedup.
## Testing
There's both already a test checking that observers don't run after
being despawned as well as a regression test for the bug that
necessitates the check this PR optimizes.
This commit is contained in:
parent
c454db88a3
commit
f570f52aa2
2 changed files with 11 additions and 8 deletions
|
@ -766,7 +766,7 @@ pub struct Archetypes {
|
||||||
/// find the archetype id by the archetype's components
|
/// find the archetype id by the archetype's components
|
||||||
by_components: HashMap<ArchetypeComponents, ArchetypeId>,
|
by_components: HashMap<ArchetypeComponents, ArchetypeId>,
|
||||||
/// find all the archetypes that contain a component
|
/// find all the archetypes that contain a component
|
||||||
by_component: ComponentIndex,
|
pub(crate) by_component: ComponentIndex,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Metadata about how a component is stored in an [`Archetype`].
|
/// Metadata about how a component is stored in an [`Archetype`].
|
||||||
|
|
|
@ -456,14 +456,17 @@ impl World {
|
||||||
if observers.map.is_empty() && observers.entity_map.is_empty() {
|
if observers.map.is_empty() && observers.entity_map.is_empty() {
|
||||||
cache.component_observers.remove(component);
|
cache.component_observers.remove(component);
|
||||||
if let Some(flag) = Observers::is_archetype_cached(event_type) {
|
if let Some(flag) = Observers::is_archetype_cached(event_type) {
|
||||||
for archetype in &mut archetypes.archetypes {
|
if let Some(by_component) = archetypes.by_component.get(component) {
|
||||||
if archetype.contains(*component) {
|
for archetype in by_component.keys() {
|
||||||
let no_longer_observed = archetype
|
let archetype = &mut archetypes.archetypes[archetype.index()];
|
||||||
.components()
|
if archetype.contains(*component) {
|
||||||
.all(|id| !cache.component_observers.contains_key(&id));
|
let no_longer_observed = archetype
|
||||||
|
.components()
|
||||||
|
.all(|id| !cache.component_observers.contains_key(&id));
|
||||||
|
|
||||||
if no_longer_observed {
|
if no_longer_observed {
|
||||||
archetype.flags.set(flag, false);
|
archetype.flags.set(flag, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue