-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
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
Make the pointers in Fetch and Query's iterators unions #6396
Conversation
archetype_entities: &[], | ||
table_id_iter: query_state.matched_table_ids.iter(), | ||
archetype_id_iter: query_state.matched_archetype_ids.iter(), | ||
id_iter: if Self::IS_DENSE { |
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.
This should be a match statement to make adding new storage types less error prone.
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.
IMO we should actually probably replace the IS_DENSE
bool with an enum?
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.
It'd make the const evals for IS_DENSE for fetches notably harder to read without the current boolean composition.
Also I thought we were avoiding match bool
?
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.
Yeah: that's part of why I suggested an enum ;)
I agree on the const evals though, so I'm fine to leave it. Adding new storage types will be very rare, and even then they'll likely be meaningfully characterized as dense or not.
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, needs more docs. The underlying strategy of using a union
here, discriminated based on compile time properties makes a lot of sense to me.
I was a bit nervous that the added complexity would make adding more storage types harder in the future, but overall this seems like it pushes us in the right direction there. More type safety, more clarity, and no per-storage-mode overhead.
Can you run some benchmarks? I'm curious to see if this makes a difference. I think we should do this even if it's perf neutral though: it's pretty clearly the right representation.
Did a quick round of microbenchmarks. Changes seem to between a small regression and a sizable gain, for the benchmarks that aren't within the noise threshold.
|
…#15283) ## Objective - Adopted #6396 ## Solution Same as #6396, we use a compile-time checked `StorageSwitch` union type to select the fetch data based on the component's storage type, saving >= 8 bytes per component fetch in a given query. Note: We forego the Query iteration change as it exists in a slightly different form now on main. ## Testing - All current tests pass locally. --------- Co-authored-by: james7132 <[email protected]> Co-authored-by: Chris Russell <[email protected]>
…bevyengine#15283) ## Objective - Adopted bevyengine#6396 ## Solution Same as bevyengine#6396, we use a compile-time checked `StorageSwitch` union type to select the fetch data based on the component's storage type, saving >= 8 bytes per component fetch in a given query. Note: We forego the Query iteration change as it exists in a slightly different form now on main. ## Testing - All current tests pass locally. --------- Co-authored-by: james7132 <[email protected]> Co-authored-by: Chris Russell <[email protected]>
Backlog cleanup: closing in favour of adopting PR #15283. |
This is a redo of #5085 and an extension of #4800.
Objective
Every
Fetch
struct initializes pointers for both storages, even though only one is ever really used. This both makes the struct bigger, and adds a minuscule amount of overhead when initializing aFetch
as it needs to zero out the unused Fetch impl.Solution
Add a compile-time discriminated
union
calledStorageSwitch
which includes the different ways a Fetch could represent a pointer to the respective storage. This allows the pointers to share the same space and there's no redundant unused memory in any of the types. (Sole exception beingWriteFetch
, which has oneusize
of unused space when used on sparse components).ReadFetch
should be the same size as a normal pointer.As sparse sets always have a reference populated when making a fetch. They're no longer wrapped in an Option, and do not need any unwrapping.
Co-Authored-By: Boxy [email protected]