bevy
bevy copied to clipboard
Extract Resources into their own dedicated storage
Objective
Resources are currently stored as a dedicated Resource archetype (ID 1). This allows for easy code reusability, but unnecessarily adds 72 bytes (on 64-bit systems) to the struct that is only used for that one archetype. It also requires several fields to be pub(crate)
which isn't ideal.
This should also remove one sparse-set lookup from fetching, inserting, and removing resources from a World
.
Solution
- Add
Resources
parallel toTables
andSparseSets
and extract the functionality used byArchetype
in it. - Remove
unique_components
fromArchetype
- Remove the
pub(crate)
onArchetype::components
. - Remove
ArchetypeId::RESOURCE
- Remove
Archetypes::resource
andArchetypes::resource_mut
Changelog
Added: Resources
type to store resources.
Added: Storages::resource
Removed: ArchetypeId::RESOURCE
Removed: Archetypes::resource
and Archetypes::resources
Removed: Archetype::unique_components
and Archetypes::unique_components_mut
Migration Guide
TODO
@james7132 can you fix this up when you get the chance? I think the fixes should be straightforward, and I'd like to unblock #4955.
Ping @BoxyUwU for attempt 5 to remember to review this 😂
@alice-i-cecile @BoxyUwU after realizing inserting and removing resources from the storage API was basically impossible to use safely from outside of bevy_ecs, I reworked a lot of this to operate with ResourceInfo
instead.
@plof27 I want your review on this too due to the impact on #1481.
Needs a Migration Guide.
[1:32 AM]Alice 🎃: Do you think this deserves the controversial label? I guess I don't really think that this is a particularly challenging PR, or something that anyone opposes [1:34 AM]james7132: Personally, no. Though the unsafe in it was what warranted the label initially I think.
Removing the controversial label; I don't think this is warranted. @JoJoJet @DJMcNab @TheRawMeatball I'd like an approval from one of you + Boxy as well though.
I think all the unsoundness to do with !Send
stuff would just disappear if we made World: !Send
hold like it ought to. I don't know whether its worth blocking this PR on the !Send
unsoundness since you could reasonably just blame the unsound World: Send
impl (#3310).
Unlike !Send
though, resources can also be !Sync
which makes the resource.rs
methods that let you go &self -> Ptr<'_>
wrong for the same reason as the !Send
unsoundness. You could probably also blame the World: Sync
impl here but iunno, the Send
/Sync
on world are kind of a mess and I don't know what we're gonna do here "long term".
Safest is probably to not merge this PR until all the methods are made unsafe with appropriate safety invariants to do with send/syncness :upside_down_face: I am not sure if we actually have any unsoundness Today to do with World: Sync
so we definitely cant merge this if we're adding some, unlike World: Send
where there is at least some form of consensus that World: Send
is wrong
Brainfarted here and forgot about the prior effort to make mutating accesses in bevy_ecs non-pub. insert
/remove
and friends should probably not be pub, and get_mut
should be more scoped than giving direct access to ResourceData. I'll add these changes soon.
Unlike !Send though, resources can also be !Sync which makes the resource.rs methods that let you go &self -> Ptr<'_> wrong for the same reason as the !Send unsoundness. You could probably also blame the World: Sync impl here but iunno, the Send/Sync on world are kind of a mess and I don't know what we're gonna do here "long term".
This is interesting since the existing unique_components
API also currently allows this IIRC. Not that we shouldn't fix this, but pointing out that this isn't necessarily a regression.
Thinking on this a bit more, Resources
within a World
are always read-only as there is no public World::storages_mut
. Perhaps it might be best to make all data related accesses, mut or not, pub(crate)
.
I think it would be fine to make it all pub(crate)
since we ought to be covering all the require functionality as World
methods anyway :thinking: doesnt really change that these methods are all kinda busted with the current send/sync impls though, even if its not publicly a problem its still a huge hazard for maintaining bevy
There's still (some?) value in being able to get the change ticks and the ArchetypeComponentId. Is that worth exposing at all?
I think we can do those in follow-up PRs. It's useful, but not essential.
This is ready: I agree with Boxy's assessment and think this makes reasoning about the internals of resources much nicer. Small perf improvements are a nice bonus.
bors r+
Pull request successfully merged into main.
Build succeeded:
- build-and-install-on-iOS
- build-android
- build (macos-latest)
- build (ubuntu-latest)
- build-wasm
- build (windows-latest)
- build-without-default-features (bevy)
- build-without-default-features (bevy_ecs)
- build-without-default-features (bevy_reflect)
- check-compiles
- check-doc
- check-missing-examples-in-docs
- ci
- markdownlint
- run-examples
- run-examples-on-wasm
- run-examples-on-windows-dx12