Refactor moving entity to new table#23151
Open
JaySpruce wants to merge 2 commits intobevyengine:mainfrom
Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Objective
When moving an entity from one table to another, we have 3 methods available:
move_to_superset_unchecked, for moving during insertion.move_to_and_drop_missing_unchecked, for moving during normal removal.move_to_and_forget_missing_unchecked, for moving duringtakeremoval.However, when looking at flecs (to steal ideas, naturally), I noticed it just has one function for moving during insertion and removal:
flecs_table_move. It also handles things a bit differently internally (details on that below).Solution
There are essentially 3 somewhat independent changes here:
move_row.movemethod toTablesand takingTableIds (rather than beingTable::move_to(&mut self, other: &mut Table)).movemethod to be more like flecs.Combining the methods
The 3 methods were already very similar;
move_to_supersetjust didn't check if components were missing. They could be combined without any of the other changes, but it's possible that insertion performance would suffer.TableIdinstead of&mut TableI believe the idea behind using references instead of IDs was to be able to cache the pointers and avoid fetching the tables more than once. However, the only callers of the
move_tomethods,BunderInserterandBundleRemover, only used the pointers for themove_tomethods and didn't need them for anything else, so there isn't much point in caching them. And being able to just use IDs makes the code nicer, since we don't have to dance around the borrow checker.Internals
Bevy's
move_tomethods don't rely on tables' columns being in any certain order; they just iterate the source table and fetch each matching column from the destination table individually.flecs_table_moverequires that tables' columns are sorted (by component ID, low-to-high). It iterates the source and destination tables at the same time (i.e. their component IDs and corresponding columns), but pauses one iterator when the other "falls behind" (has a lower component ID). If the source table falls behind, the source table's current component ID was removed, and if the destination table falls behind, the destination table's current component ID was added.As it turns out, Bevy's tables are sorted in practice, we just never guaranteed or relied on it. A table's list of component IDs are sorted to use as the key in a
HashMap, and the same list is used to build the table. So we can just make it official byasserting that a table's components are sorted when the table is finalized (TableBuilder::build).Evidently, iterating the destination table is faster than fetching from it repeatedly:
Misc
There's a
PERFcomment that has survived since 2021 (#2673) and I'm not really sure what it means:I didn't want to remove it without saying anything, but I think it's lived long enough.