- 
          
 - 
                Notifications
    
You must be signed in to change notification settings  - Fork 4.2k
 
Stop storing access for all systems #19477
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Stop storing access for all systems #19477
Conversation
…e parameter to init_access.
Create wrapper types in the scheduling module to store the access where necessary.
…cess-ii # Conflicts: # crates/bevy_ecs/src/system/builder.rs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Absolutely stellar implementation! The code is remarkably clean and well-structured.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't really like the system.system and condition.condition stuttering with the SystemWithAccess and the ConditionWithAccess struct, but in general, I think this is a really good change. If it passes CI, I'll approve it.
| 
               | 
          ||
| // SAFETY: no component value access | ||
| unsafe impl SystemParam for SystemName<'_> { | ||
| type State = Cow<'static, str>; | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did you change this? I'm curious.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did you change this? I'm curious.
Oh, right, I meant to leave a note about that!
I removed the SystemMeta parameter from init_state since I thought it would only be used by the parts that had moved to init_access.  This turned out to be the one place that actually initialized the state from the SystemMeta!  Note that for most systems, name is a Cow::Borrowed, so this won't be any slower.
I can restore the SystemMeta parameter if anyone is opposed to this change.  We might want to do something else to ensure that existing calls to init_state fail to compile, though, since users will need to change those to add calls to init_access.
I think the ideal solution here would be to let get_param borrow from SystemMeta.  That would also avoid needing to clone() it in ParamSet.  But that would touch a lot of code for a fairly minor performance improvement, especially since this PR already saves having to clone the access.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, this seems good. Thanks for the explanation.
…cess-ii # Conflicts: # crates/bevy_ecs/src/schedule/executor/mod.rs # crates/bevy_ecs/src/system/adapter_system.rs # crates/bevy_ecs/src/system/combinator.rs # crates/bevy_ecs/src/system/exclusive_function_system.rs # crates/bevy_ecs/src/system/function_system.rs # crates/bevy_ecs/src/system/observer_system.rs # crates/bevy_ecs/src/system/schedule_system.rs # crates/bevy_ecs/src/system/system.rs
…cess-ii # Conflicts: # crates/bevy_ecs/src/schedule/executor/mod.rs # crates/bevy_ecs/src/schedule/schedule.rs # crates/bevy_ecs/src/system/adapter_system.rs # crates/bevy_ecs/src/system/combinator.rs # crates/bevy_ecs/src/system/exclusive_function_system.rs # crates/bevy_ecs/src/system/function_system.rs # crates/bevy_ecs/src/system/mod.rs # crates/bevy_ecs/src/system/observer_system.rs # crates/bevy_ecs/src/system/schedule_system.rs # crates/bevy_ecs/src/system/system.rs # crates/bevy_ecs/src/world/unsafe_world_cell.rs
Update PR number in migration guide.
…cess-ii # Conflicts: # crates/bevy_ecs/src/removal_detection.rs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well done, I like this! Getting rid of both accesses in System will also make things easier for my manual impls. 😄
# Objective Reduce memory usage by storing fewer copies of `FilteredAccessSet<ComponentId>`. Currently, the `System` trait exposes the `component_access_set` for the system, which is used by the multi-threaded executor to determine which systems can run concurrently. But because it is available on the trait, it needs to be stored for *every* system, even ones that are not run by the executor! In particular, it is never needed for observers, or for the inner systems in a `PipeSystem` or `CombinatorSystem`. ## Solution Instead of exposing the access from a method on `System`, return it from `System::initialize`. Since it is still needed during scheduling, store the access alongside the boxed system in the schedule. That's not quite enough for systems built using `SystemParamBuilder`s, though. Those calculate the access in `SystemParamBuilder::build`, which happens earlier than `System::initialize`. To handle those, we separate `SystemParam::init_state` into `init_state`, which creates the state value, and `init_access`, which calculates the access. This lets `System::initialize` call `init_access` on a state that was provided by the builder. An additional benefit of that separation is that it removes the need to duplicate access checks between `SystemParamBuilder::build` and `SystemParam::init_state`. --------- Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Objective
Reduce memory usage by storing fewer copies of
FilteredAccessSet<ComponentId>.Currently, the
Systemtrait exposes thecomponent_access_setfor the system, which is used by the multi-threaded executor to determine which systems can run concurrently. But because it is available on the trait, it needs to be stored for every system, even ones that are not run by the executor! In particular, it is never needed for observers, or for the inner systems in aPipeSystemorCombinatorSystem.Solution
Instead of exposing the access from a method on
System, return it fromSystem::initialize. Since it is still needed during scheduling, store the access alongside the boxed system in the schedule.That's not quite enough for systems built using
SystemParamBuilders, though. Those calculate the access inSystemParamBuilder::build, which happens earlier thanSystem::initialize. To handle those, we separateSystemParam::init_stateintoinit_state, which creates the state value, andinit_access, which calculates the access. This letsSystem::initializecallinit_accesson a state that was provided by the builder.An additional benefit of that separation is that it removes the need to duplicate access checks between
SystemParamBuilder::buildandSystemParam::init_state.