mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 15:14:50 +00:00
57733bbec3
# 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.
50 lines
1.2 KiB
TOML
50 lines
1.2 KiB
TOML
[package]
|
|
name = "bevy_ecs"
|
|
version = "0.14.0-dev"
|
|
edition = "2021"
|
|
description = "Bevy Engine's entity component system"
|
|
homepage = "https://bevyengine.org"
|
|
repository = "https://github.com/bevyengine/bevy"
|
|
license = "MIT OR Apache-2.0"
|
|
keywords = ["ecs", "game", "bevy"]
|
|
categories = ["game-engines", "data-structures"]
|
|
|
|
[features]
|
|
trace = []
|
|
multi-threaded = ["bevy_tasks/multi-threaded"]
|
|
bevy_debug_stepping = []
|
|
default = ["bevy_reflect", "bevy_debug_stepping"]
|
|
|
|
[dependencies]
|
|
bevy_ptr = { path = "../bevy_ptr", version = "0.14.0-dev" }
|
|
bevy_reflect = { path = "../bevy_reflect", version = "0.14.0-dev", optional = true }
|
|
bevy_tasks = { path = "../bevy_tasks", version = "0.14.0-dev" }
|
|
bevy_utils = { path = "../bevy_utils", version = "0.14.0-dev" }
|
|
bevy_ecs_macros = { path = "macros", version = "0.14.0-dev" }
|
|
|
|
bitflags = "2.3"
|
|
concurrent-queue = "2.4.0"
|
|
fixedbitset = "0.4.2"
|
|
rustc-hash = "1.1"
|
|
serde = "1"
|
|
thiserror = "1.0"
|
|
nonmax = "0.5"
|
|
|
|
[dev-dependencies]
|
|
rand = "0.8"
|
|
static_assertions = "1.1.0"
|
|
|
|
[[example]]
|
|
name = "events"
|
|
path = "examples/events.rs"
|
|
|
|
[[example]]
|
|
name = "resources"
|
|
path = "examples/resources.rs"
|
|
|
|
[[example]]
|
|
name = "change_detection"
|
|
path = "examples/change_detection.rs"
|
|
|
|
[lints]
|
|
workspace = true
|