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

Remove archetype_component_access from QueryState #12474

Conversation

james7132
Copy link
Member

@james7132 james7132 commented Mar 14, 2024

Objective

QueryState::archetype_component_access is only really ever used to extend SystemMeta's. It can be removed to save some memory for every Query in an app.

Solution

  • Remove it.
  • Have new_archetype pass in a &mut Access<ArchetypeComponentId> instead and pull it from SystemMeta directly.
  • Split QueryState::new from QueryState::new_with_access and a common QueryState::new_uninitialized.
  • Split new_archetype into an internal and public version. Call the internal version in update_archetypes.

This should make it faster to construct new QueryStates, and by proxy lenses and joins as well.

matched_tables also similarly is only used to deduplicate inserting into matched_table_ids. If we can find another efficient way to do so, it might also be worth removing.

The generated assembly reflects this well, with all of the access related updates in QueryState being removed.


Changelog

Removed: QueryState::archetype_component_access.
Changed: QueryState::new_archetype now takes a &mut Access<ArchetypeComponentId> argument, which will be updated with the new accesses.
Changed: QueryState::update_archetype_component_access now takes a &mut Access<ArchetypeComponentId> argument, which will be updated with the new accesses.

Migration Guide

QueryState::archetype_component_access has been removed. This can be worked around by accessing the surrounding SystemState's instead. If you needed this explicitly for QueryState, please file an issue.

@james7132 james7132 added A-ECS Entities, components, systems, and events C-Performance A change motivated by improving speed, memory usage or compile times C-Breaking-Change A breaking change to Bevy's public API that needs to be noted in a migration guide labels Mar 14, 2024
@james7132 james7132 requested a review from JoJoJet March 14, 2024 07:46
@james7132 james7132 changed the title Remove archetye_component_access from QueryState Remove archetype_component_access from QueryState Mar 14, 2024
@james7132 james7132 marked this pull request as ready for review March 14, 2024 08:32
Copy link
Member

@JoJoJet JoJoJet left a comment

Choose a reason for hiding this comment

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

LGTM. I always appreciate these simple-in-hindsight optimizations with wide-reaching effects

I'd be interested to see if there's a measurable impact on our benchmarks, or if the savings are mainly for memory and cache usage

crates/bevy_ecs/src/query/state.rs Outdated Show resolved Hide resolved
@james7132
Copy link
Member Author

I'd be interested to see if there's a measurable impact on our benchmarks, or if the savings are mainly for memory and cache usage

I don't really expect them to show up in the microbenchmarks since they all hit the ArchetypeGeneration check, come up empty, and return immediately. Might improve it a little bit by reducing instruction cache pressure a bit by having less codegen though.

@alice-i-cecile alice-i-cecile added the S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it label Mar 17, 2024
@alice-i-cecile alice-i-cecile added this pull request to the merge queue Mar 17, 2024
Merged via the queue into bevyengine:main with commit eebf3d6 Mar 17, 2024
26 checks passed
github-merge-queue bot pushed a commit that referenced this pull request Mar 30, 2024
# Objective
Other than the exposed functions for reading matched tables and
archetypes, a `QueryState` does not actually need both internal Vecs for
storing matched archetypes and tables. In practice, it will only use one
of the two depending on if it uses dense or archetypal iteration.

Same vein as #12474. The goal is to reduce the memory overhead of using
queries, which Bevy itself, ecosystem plugins, and end users are already
fairly liberally using.

## Solution
Add `StorageId`, which is a union over `TableId` and `ArchetypeId`, and
store only one of the two at runtime. Read the slice as if it was one ID
depending on whether the query is dense or not.

This follows in the same vein as #5085; however, this one directly
impacts heap memory usage at runtime, while #5085 primarily targeted
transient pointers that might not actually exist at runtime.

---

## Changelog
Changed: `QueryState::matched_tables` now returns an iterator instead of
a reference to a slice.
Changed: `QueryState::matched_archetypes` now returns an iterator
instead of a reference to a slice.

## Migration Guide
`QueryState::matched_tables` and `QueryState::matched_archetypes` does
not return a reference to a slice, but an iterator instead. You may need
to use iterator combinators or collect them into a Vec to use it as a
slice.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
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-Breaking-Change A breaking change to Bevy's public API that needs to be noted in a migration guide C-Performance A change motivated by improving speed, memory usage or compile times S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants