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

Remote entity reservation v2 #18266

Open
wants to merge 37 commits into
base: main
Choose a base branch
from

Conversation

ElliottjPierce
Copy link
Contributor

@ElliottjPierce ElliottjPierce commented Mar 11, 2025

fixes #18003

Objective

Long story short: we need to be able to reserve entities from outside &World.

This is an alternative to #18195.

Solution

Thanks to everyone who helped brainstorm on discord. There's still ideas being tossed around, but here's how this PR works:

All entity meta is kept in a single unlocked Vec<EntityMeta>. We keep a pending list that can be used remotely to reserve entities, etc.

When we allocate an entity directly, we pop from the new owned: Vec<Entity>, and if it's empty, we reserve some more entities in bulk. These entities are not flushed.

To ensure we don't loose entities anywhere, flushing rebalances pending and owned. We can tweak the proportions later, but currently, it splits the pending entities between the two evenly.

Practical Change

It used to be that a brand new Entities would yield sequential indices via alloc. This was never a guarantee, but many tests relied on this ordering. The ordering is still deterministic but is no longer sequential or aligned. In other words, if you allocate 5 entities. You might get back indices [0, 4, 2, 6, 7]. Generally entities like this are opaque and this should not affect users. However, tests and benchmarks that depend on this previous, not guaranteed behavior had to be reworked.

One practical effect this may have is that systems that run through Entitys sequentially, will have a different order. This may affect query orders, observer ordering, etc. None of these things were guarantees before, but this may expose some existing bugs in those systems.

I suspect this is why some rendering systems broke.

Future Work

Flushing is now completely unnecessary for many of the interactions with [Entities]. We still need to do it before applying command queues, etc, but we don't need to flush before allocations or freeing. If we go in this direction, we should explore relaxing those requirements for performance.

Testing

Functionality hasn't changed, so no new tests were added. A few old tests were revised because of the practical changes.

However, it makes sense to add tests for remote registration, so if anyone has specific concerns, I'd be happy to write a test for it.

@alice-i-cecile alice-i-cecile added A-ECS Entities, components, systems, and events C-Feature A new feature, making something new possible X-Controversial There is active debate or serious implications around merging this PR S-Needs-Review Needs reviewer attention (from anyone!) to move forward M-Needs-Migration-Guide A breaking change to Bevy's public API that needs to be noted in a migration guide labels Mar 11, 2025
@@ -50,6 +50,9 @@ impl ArchetypeRow {
/// Index indicating an invalid archetype row.
/// This is meant to be used as a placeholder.
pub const INVALID: ArchetypeRow = ArchetypeRow(u32::MAX);
/// This is the same as [`Self::INVALID`], but it signals to [`Entities`](crate::entity::Entities)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to see this expanded to explain why it exists.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically, when we reserve Entitys from EntityReservations for Entities::owned, we don't want to flush them like normal. They haven't been requested yet, so the flush doesn't make sense, and when they are requested by Entities::alloc, the caller will be the one to Entities::set the EntityLocation.

In principal, we could just have a HashSet of Entitys that have been in Entities::owned since the last flush, but that lookup takes time and memory.

Instead, by keeping a special EntityLocation::INVALID_BUT_DONT_FLUSH, we can determine whether or not to flush based only on if meta.location == EntityLocation::INVALID or not.

Hopefully that makes sense. This is complicated.

}
}

/// This allows entity reservation.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remember to beef these up a bit once we have consensus on the basic mechanism.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Absolutely. Just don't want to write full docs until we settle on a design. 🥲

This was the big piece of the puzzle I was missing.
Copy link
Contributor

Your PR caused a change in the graphical output of an example or rendering test. This might be intentional, but it could also mean that something broke!
You can review it at https://pixel-eagle.com/project/B04F67C0-C054-4A6F-92EC-F599FEC2FD1D?filter=PR-18266

If it's expected, please add the M-Deliberate-Rendering-Change label.

If this change seems unrelated to your PR, you can consider updating your PR to target the latest main branch, either by rebasing or merging main into it.

entity allocation order is not guaranteed.
/// # Dropping
///
/// All reserved entities will continue to be reserved after dropping, *including those that were not iterated*.
/// Dropping this without finishing the iterator is effectively leaking an entity.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How bad is "leaking an entity"? Leaking memory is pretty bad but maybe leaking an index is less so?

Copy link
Contributor Author

@ElliottjPierce ElliottjPierce Mar 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not that bad at all, and it isn't done anywhere in Bevy that I know of. The docs here were just incomplete. This is irrelevant to the rest of these changes. I just figured, while I'm here...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah okay I gotcha, thank you!

Copy link
Contributor

Your PR caused a change in the graphical output of an example or rendering test. This might be intentional, but it could also mean that something broke!
You can review it at https://pixel-eagle.com/project/B04F67C0-C054-4A6F-92EC-F599FEC2FD1D?filter=PR-18266

If it's expected, please add the M-Deliberate-Rendering-Change label.

If this change seems unrelated to your PR, you can consider updating your PR to target the latest main branch, either by rebasing or merging main into it.

This gets rid of that pesky linear search.
Copy link
Contributor

Your PR caused a change in the graphical output of an example or rendering test. This might be intentional, but it could also mean that something broke!
You can review it at https://pixel-eagle.com/project/B04F67C0-C054-4A6F-92EC-F599FEC2FD1D?filter=PR-18266

If it's expected, please add the M-Deliberate-Rendering-Change label.

If this change seems unrelated to your PR, you can consider updating your PR to target the latest main branch, either by rebasing or merging main into it.

This lets us continue to check all entities directly.
Copy link
Contributor

Your PR caused a change in the graphical output of an example or rendering test. This might be intentional, but it could also mean that something broke!
You can review it at https://pixel-eagle.com/project/B04F67C0-C054-4A6F-92EC-F599FEC2FD1D?filter=PR-18266

If it's expected, please add the M-Deliberate-Rendering-Change label.

If this change seems unrelated to your PR, you can consider updating your PR to target the latest main branch, either by rebasing or merging main into it.

Copy link
Contributor

Your PR caused a change in the graphical output of an example or rendering test. This might be intentional, but it could also mean that something broke!
You can review it at https://pixel-eagle.com/project/B04F67C0-C054-4A6F-92EC-F599FEC2FD1D?filter=PR-18266

If it's expected, please add the M-Deliberate-Rendering-Change label.

If this change seems unrelated to your PR, you can consider updating your PR to target the latest main branch, either by rebasing or merging main into it.

Copy link
Contributor

Your PR caused a change in the graphical output of an example or rendering test. This might be intentional, but it could also mean that something broke!
You can review it at https://pixel-eagle.com/project/B04F67C0-C054-4A6F-92EC-F599FEC2FD1D?filter=PR-18266

If it's expected, please add the M-Deliberate-Rendering-Change label.

If this change seems unrelated to your PR, you can consider updating your PR to target the latest main branch, either by rebasing or merging main into it.

1 similar comment
Copy link
Contributor

Your PR caused a change in the graphical output of an example or rendering test. This might be intentional, but it could also mean that something broke!
You can review it at https://pixel-eagle.com/project/B04F67C0-C054-4A6F-92EC-F599FEC2FD1D?filter=PR-18266

If it's expected, please add the M-Deliberate-Rendering-Change label.

If this change seems unrelated to your PR, you can consider updating your PR to target the latest main branch, either by rebasing or merging main into it.

entity ordering can not be relied on.
Index was 0 previously but is now 255
the order and index of the entities had changed.
Copy link
Contributor

Your PR caused a change in the graphical output of an example or rendering test. This might be intentional, but it could also mean that something broke!
You can review it at https://pixel-eagle.com/project/B04F67C0-C054-4A6F-92EC-F599FEC2FD1D?filter=PR-18266

If it's expected, please add the M-Deliberate-Rendering-Change label.

If this change seems unrelated to your PR, you can consider updating your PR to target the latest main branch, either by rebasing or merging main into it.

@ElliottjPierce
Copy link
Contributor Author

This seems to have a breaking change with testbed ui's text wrap. See here.

I tested it locally and the text seems to not be rendering (aside from its background) unless the mouse is hovering over it. When the mouse isn't hovering over a text item, only the most recently hovered item is rendered. There's no meaningful logs either.

I have no knowledge of the internals of the text system, and I have no idea why this is broken with this PR. It seems like this is actually an existing bug that this PR just uncovered, but IDK. AFAIK the text system doesn't depend on observer ordering or particularly ordered queries, so I can't think of a reason this would break.

@ElliottjPierce
Copy link
Contributor Author

@alice-i-cecile I apologize for the misdirection, but I actually don't think this needs a migration guide. I was almost certain it did before, but now that the dust has settled, I don't see any breaking changes. Let me know if I'm missing something.

Copy link
Contributor

Your PR caused a change in the graphical output of an example or rendering test. This might be intentional, but it could also mean that something broke!
You can review it at https://pixel-eagle.com/project/B04F67C0-C054-4A6F-92EC-F599FEC2FD1D?filter=PR-18266

If it's expected, please add the M-Deliberate-Rendering-Change label.

If this change seems unrelated to your PR, you can consider updating your PR to target the latest main branch, either by rebasing or merging main into it.

@ickshonpe
Copy link
Contributor

ickshonpe commented Mar 12, 2025

This seems to have a breaking change with testbed ui's text wrap. See here.

I tested it locally and the text seems to not be rendering (aside from its background) unless the mouse is hovering over it. When the mouse isn't hovering over a text item, only the most recently hovered item is rendered. There's no meaningful logs either.

I have no knowledge of the internals of the text system, and I have no idea why this is broken with this PR. It seems like this is actually an existing bug that this PR just uncovered, but IDK. AFAIK the text system doesn't depend on observer ordering or particularly ordered queries, so I can't think of a reason this would break.

Yep revealed bug, the sort key for the transparent UI phase uses a pair of the stack index and the render entities index. I guess the render entity index was intended to break ties but it's not needed as the sort is stable and if the entity indices aren't sequential it messes up the draw order so the text in the example gets drawn beneath the colored background panels.

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 M-Needs-Migration-Guide A breaking change to Bevy's public API that needs to be noted in a migration guide S-Needs-Review Needs reviewer attention (from anyone!) to move forward X-Controversial There is active debate or serious implications around merging this PR
Projects
Status: Respond (With Priority)
Development

Successfully merging this pull request may close these issues.

Reserve entities from async
4 participants