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 as entities #16618

Open
andriyDev opened this issue Dec 2, 2024 · 1 comment
Open

Systems as entities #16618

andriyDev opened this issue Dec 2, 2024 · 1 comment
Labels
A-ECS Entities, components, systems, and events C-Feature A new feature, making something new possible D-Complex Quite challenging from either a design or technical perspective. Ask for help! S-Needs-Design This issue requires design work to think about how it would best be accomplished

Comments

@andriyDev
Copy link
Contributor

andriyDev commented Dec 2, 2024

Background

Today, bevy_ecs can roughly be split into two parts:

  1. Data Storage and Access: This includes World, entities, components, resources, archetypes and querying.
  2. Systems and Schedules: This is all the infrastructure for creating systems and executing them.

The data storage part is very flexible and powerful. It has facilities for storing arbitrary data on objects, composing data on objects, reacting to changes in data, and so on.

On the other hand, schedules are a hand crafted storage solution for systems which includes all manner of metadata: system name, before/after relations, system sets it belongs to, etc.

As a result, we have to build a lot of APIs. Schedules today can't have systems be removed (#279, wow that's an old issue). We'd have to come up with an ID scheme for systems, provide a function to remove systems, and also make sure the schedule graph reacts appropriately to the change.

Proposal: Systems-as-entities

(queue anything-as-entities meme)

Instead of building more stuff on top of the system storage, we can instead rewrite it to use the data storage and access part! Now we don't need an ID scheme for systems: it's just an Entity. Now we don't need a function to remove systems: that's just despawning an entity. As for having the schedule graphs react to changes, we have several tools to handle this. Change detection, hooks, and observers could be used.

As part of this, we will likely want schedules and system sets to also be entities. Systems can then have a system set or schedule component that matches the particular type.

Issues that help this effort

Immutable Components (#16372)

Today, we likely need to use change detection to keep things in sync. With immutable components, we can just use hooks to sync any schedule data structures.

🌈 Relations (#3742)

Today, we either need to store before/after relationships as one component for all a system's constraints, or we need to spawn an entity to represent that constraint. Either way, these are both cumbersome to manage. With relations, we can use them to represent all the before/after constraints as relations. Finding all edges is very easy then.

Similarly, schedules and system sets could use relations to define which systems are in the schedule or system set.

Risks

  • This would be replacing a ton of our schedule code. New code can be buggy!
  • Users may accidentally mutate the system entities without realizing it by either deleting their entities or mutating their components.
    • This could be fixed with a separate "schedule world", which will be a world that just holds the systems, schedules, and system sets.
  • Mutability may be hard to juggle. I'm not certain of this problem - this may be an implementation detail. The schedule will likely still hold a schedule graph representation of some kind which we can probably just take out of the corresponding component and put it back once we're done.

Prior Art

@andriyDev andriyDev added C-Feature A new feature, making something new possible S-Needs-Triage This issue needs to be labelled labels Dec 2, 2024
@hymm hymm added A-ECS Entities, components, systems, and events D-Complex Quite challenging from either a design or technical perspective. Ask for help! and removed S-Needs-Triage This issue needs to be labelled labels Dec 3, 2024
@hymm
Copy link
Contributor

hymm commented Dec 3, 2024

Mutability is probably the biggest problem here to solve. i.e. How do you get mutable access to all the systems in the schedule in a safe way? You have to have exclusive access of the BoxedSystem and the cached system params to be able to run a system safely. While you can query for all the systems in a schedule, you have to drop the query before you can run the schedule, since that requires passing &mut World to the schedule. So we either need to hokey-pokey the systems or use some sort of interior mutability:

  • @maniwani suggested storing the systems in an Arc Mutex. This will introduce the possibility of panics/deadlocks if you try to run the same system on two different threads. The cost of an uncontested mutex is fairly low and arcing the systems vs boxing will also introduce a bit of overhead. This extra overhead likely won't be measurable, but should be checked. But there will also be more overhead as we'll probably we storing the system param caches as separate components which will also need to be arc mutexed.
  • The hokey-pokey would probably be something like storing the system in a Option and remove the data as needed. I suspect that this will be too expensive as we potentially have low 1000's of systems to run every frame. We do this with schedules and it already has a noticeable impact on frame times.
  • Some in between method where schedules still own some of the system's data. There probably a sliding scale here of what data the schedule owns vs the world (BoxedSystem, system meta data, system cached params, etc). This would allow some of the data to be accessible, but not sure if there's a line to draw here that actually makes sense.

This could be fixed with a separate "schedule world", which will be a world that just holds the systems, schedules, and system sets.This could be fixed with a separate "schedule world", which will be a world that just holds the systems, schedules, and system sets.

I'm not sure this makes sense as we need queries as entities for relations. This needs observers on adding/removing components in the main world to update the query caches of the matching archetypes. So these need to live in the main world. I suppose it could work if the observers in the main world have exclusive access to the schedule world, but this would block the observers from running in parallel (if we ever enable that).

I'd say other risks are that moving systems into the world might make some future scheduling algorithms harder to implement or block perf improvements. Scheduling is a very perf sensitive part of the ecs and not being able to use customized data structures for storing systems could lock us out of making certain improvements. But that's all rather nebulous, so it's not something that I would consider blocking.

@BenjaminBrienen BenjaminBrienen added the S-Needs-Design This issue requires design work to think about how it would best be accomplished label Dec 12, 2024
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-Complex Quite challenging from either a design or technical perspective. Ask for help! S-Needs-Design This issue requires design work to think about how it would best be accomplished
Projects
None yet
Development

No branches or pull requests

3 participants