bevy/crates/bevy_ecs/src
James Liu 57733bbec3
Use NonMaxUsize for non-component SparseSets (#12083)
# Objective
Adoption of #2104 and #11843. The `Option<usize>` wastes 3-7 bytes of
memory per potential entry, and represents a scaling memory overhead as
the ID space grows.

The goal of this PR is to reduce memory usage without significantly
impacting common use cases.

Co-Authored By: @NathanSWard 
Co-Authored By: @tygyh 

## Solution
Replace `usize` in `SparseSet`'s sparse array with
`nonmax::NonMaxUsize`. NonMaxUsize wraps a NonZeroUsize, and applies a
bitwise NOT to the value when accessing it. This allows the compiler to
niche the value and eliminate the extra padding used for the `Option`
inside the sparse array, while moving the niche value from 0 to
usize::MAX instead.

Checking the [diff in x86 generated
assembly](6e4da653cc),
this change actually results in fewer instructions generated. One
potential downside is that it seems to have moved a load before a
branch, which means we may be incurring a cache miss even if the element
is not there.

Note: unlike #2104 and #11843, this PR only targets the metadata stores
for the ECS and not the component storage itself. Due to #9907 targeting
`Entity::generation` instead of `Entity::index`, `ComponentSparseSet`
storing only up to `u32::MAX` elements would become a correctness issue.

This will come with a cost when inserting items into the SparseSet, as
now there is a potential for a panic. These cost are really only
incurred when constructing a new Table, Archetype, or Resource that has
never been seen before by the World. All operations that are fairly cold
and not on any particular hotpath, even for command application.

---

## Changelog
Changed: `SparseSet` now can only store up to `usize::MAX - 1` elements
instead of `usize::MAX`.
Changed: `SparseSet` now uses 33-50% less memory overhead per stored
item.
2024-03-03 14:55:27 +00:00
..
entity Document instability of Entity's internal representation (#12249) 2024-03-02 18:37:52 +00:00
identifier fix some typos (#12038) 2024-02-22 18:55:22 +00:00
query remove repetitive code (#12270) 2024-03-03 07:58:22 +00:00
reflect Move commands module into bevy::ecs::world (#12234) 2024-03-02 23:13:45 +00:00
schedule Replace FromWorld requirement on ReflectResource and reflect Resource for State<S> (#12136) 2024-02-27 15:49:39 +00:00
storage Use NonMaxUsize for non-component SparseSets (#12083) 2024-03-03 14:55:27 +00:00
system Move commands module into bevy::ecs::world (#12234) 2024-03-02 23:13:45 +00:00
world remove repetitive code (#12270) 2024-03-03 07:58:22 +00:00
archetype.rs Component Lifecycle Hooks and a Deferred World (#10756) 2024-03-01 14:59:22 +00:00
bundle.rs remove repetitive code (#12270) 2024-03-03 07:58:22 +00:00
change_detection.rs bevy_ecs address trivial cases of unsafe_op_in_unsafe_fn (#11861) 2024-02-22 00:04:38 +00:00
component.rs Replace init_component_info with register_component_hooks (#12244) 2024-03-02 05:27:48 +00:00
event.rs Fix bug where events are not being dropped (#11528) 2024-02-02 21:14:54 +00:00
lib.rs Component Lifecycle Hooks and a Deferred World (#10756) 2024-03-01 14:59:22 +00:00
removal_detection.rs Docs reflect that RemovalDetection also yields despawned entities (#11795) 2024-02-10 11:18:05 +00:00