Skip to content
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

Systems with parallelizable mutable access to multiple worlds. #16933

Open
ElliottjPierce opened this issue Dec 22, 2024 · 1 comment · May be fixed by #17198
Open

Systems with parallelizable mutable access to multiple worlds. #16933

ElliottjPierce opened this issue Dec 22, 2024 · 1 comment · May be fixed by #17198
Labels
A-ECS Entities, components, systems, and events C-Feature A new feature, making something new possible D-Modest A "normal" level of difficulty; suitable for simple features or challenging fixes S-Needs-Design This issue requires design work to think about how it would best be accomplished

Comments

@ElliottjPierce
Copy link

TLDR

This proposes systems that can reference multiple worlds mutable while maintaining maximum parallelization. This could open up the doors for dramatic performance improvements down the road, especially in extraction schedules for sub-apps. It would also improve/replace some utility abstractions found in bevy_render, making similar performance gains possible for additional sub-apps, most notably physics sub-apps.

What problem does this solve or what need does it fill?

Currently, communicating mutably between two worlds is challenging. This comes up a lot during extract phases for sub-apps, which ends up being a performance bottleneck because it limits what can be parallelized. Bevy has some abstractions that make this more convinient, especially in bevy_render, but they all have some form of limitation.

It would be great to be able to be able to have a resource that contains a World, or World ptr, etc, which can then be referenced by system parameters. For example, something like this:

#[derive(Resource)]
struct MyWorldRef(World);

fn my_system(main_time: ResMut<Time>, other_time: SomeAbstraction<MyWorldRef, ResMut<Time>>) {
    ...
}

This is similar to bevy_render's Extract system parameter, but that only works for read-only access. Other abstractions are possible but are complicated because of the following:

Currently the above magical abstraction is not feasible because the SystemMeta's access lists do not store WorldIds. In other words, my_system is invalid because it requires multiple mutable accesses to the Time resource, even though the ResMuts actually refer to different worlds.

What solution would you like?

I am no expert in the internals of bevy's ecs, but it looks to me that by adding a WorldId to each ComponentId and ArchetypeComponentId in the SystemMeta Access list, these abstractions would be possible.

To prevent the memory overhead of storing largely redundant WorldIds (usually it will all be for the same world), it would be more realistic to have one Access and FilteredAccessSet per WorldId that the system references.

This is definitely contentious and is just an idea. I am very open to alternatives.

What alternative(s) have you considered?

It seems to me that the best alternatives currently possible are from bevy_render's Extract family of abstractions, but those have the downsides and reduced capabilities as shown above. These abstractions could be improved and moved to another crate. I would imagine similar patters are used in various other community sub-apps, especially physics sub-apps.

Alternatively, each conflicting component and resource could be wrapped in a type like FromWorld12<ComponentType>, but that involves redundant registrations and requires compile-time knowledge of the different worlds.

Additional context

This issue deals with mutable communication. I recently opened a related issue for immutable communication, #16923. That has more context for my specific use case, but the nature of these issues are different.

Depending on the how this is implemented, it may need to be designed for/around #16618.

Benefits

If some version of this is implemented, here are some potential benefits down the road:

  • More and more automated parallelization of sub-app extract phases could be implemented.
  • It would be easier to add to extraction schedules.
  • A major change: sub-app worlds could be made available to the main world, and a unified extraction schedule could be added to the main world. This would enable significant parallelism by letting much of sub-app extractions happen in parallel. Ex: Render and Physics sub-apps may be able to do most extraction in parallel.
@ElliottjPierce ElliottjPierce added C-Feature A new feature, making something new possible S-Needs-Triage This issue needs to be labelled labels Dec 22, 2024
@PPakalns
Copy link
Contributor

PPakalns commented Dec 22, 2024

Would be interested in this too.

Currently I am using something similar to Arc<RwLock<bevy::app::App>> to store access to subworld inside InnerWorld resource.

fn system_that_accesses_inner_world_immutable(
    inner_world: Option<Res<InnerWorld>>,
    ... // Main world query and resource access
) -> Option<()> {
    let inner_world = inner_world.as_ref().and_then(|v| v.get().ok())?;
    let inner_world = inner_world.world();

    // Query state is kept up to date in inner world
    let inner_world_query = InnerWorldQueryState::<SomeQuery>::retrieve_plain(inner_world)?;

    let inner_world_res1 = inner_world.get_resource::<Res1>()?;
    let inner_world_res2 = inner_world.get_resource::<Res2>()?;

    ... // Process retrieved data and store it in main world
}

This approach allows me to execute subworld and extract, insert data during any step of schedule.

Would be nice if there would be better support for accessing, executing and inserting, removing data from SubApp/SubWorld.

@BenjaminBrienen BenjaminBrienen added A-ECS Entities, components, systems, and events S-Needs-Design This issue requires design work to think about how it would best be accomplished D-Modest A "normal" level of difficulty; suitable for simple features or challenging fixes and removed S-Needs-Triage This issue needs to be labelled labels Dec 24, 2024
@ElliottjPierce ElliottjPierce linked a pull request Jan 6, 2025 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-ECS Entities, components, systems, and events C-Feature A new feature, making something new possible D-Modest A "normal" level of difficulty; suitable for simple features or challenging fixes S-Needs-Design This issue requires design work to think about how it would best be accomplished
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants