-
-
Notifications
You must be signed in to change notification settings - Fork 4k
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.
type Target = str; | ||
fn deref(&self) -> &Self::Target { | ||
self.name() | ||
} | ||
} | ||
|
||
// 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
System
trait exposes thecomponent_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 aPipeSystem
orCombinatorSystem
.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
SystemParamBuilder
s, though. Those calculate the access inSystemParamBuilder::build
, which happens earlier thanSystem::initialize
. To handle those, we separateSystemParam::init_state
intoinit_state
, which creates the state value, andinit_access
, which calculates the access. This letsSystem::initialize
callinit_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
andSystemParam::init_state
.