Update to fixedbitset 0.5 (#12512)

# Objective
Improve code quality involving fixedbitset.

## Solution
Update to fixedbitset 0.5. Use the new `grow_and_insert` function
instead of `grow` and `insert` functions separately.

This should also speed up most of the set operations involving
fixedbitset. They should be ~2x faster, but testing this against the
stress tests seems to show little to no difference. The multithreaded
executor doesn't seem to be all that much faster in many_cubes and
many_foxes. These use cases are likely dominated by other operations or
the bitsets aren't big enough to make them the bottleneck.

This introduces a duplicate dependency due to petgraph and wgpu, but the
former may take some time to update.

## Changelog
Removed: `Access::grow`

## Migration Guide
`Access::grow` has been removed. It's no longer needed. Remove all
references to it.
This commit is contained in:
James Liu 2024-03-17 11:43:05 -07:00 committed by GitHub
parent 1e1e11c4a6
commit 8327ce85d8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 15 additions and 35 deletions

View file

@ -28,7 +28,7 @@ bevy_transform = { path = "../bevy_transform", version = "0.14.0-dev" }
bevy_hierarchy = { path = "../bevy_hierarchy", version = "0.14.0-dev" }
# other
fixedbitset = "0.4"
fixedbitset = "0.5"
petgraph = { version = "0.6", features = ["serde-1"] }
ron = "0.8"
serde = "1"

View file

@ -25,7 +25,7 @@ petgraph = "0.6"
bitflags = "2.3"
concurrent-queue = "2.4.0"
fixedbitset = "0.4.2"
fixedbitset = "0.5"
rustc-hash = "1.1"
serde = "1"
thiserror = "1.0"

View file

@ -97,26 +97,17 @@ impl<T: SparseSetIndex> Access<T> {
}
}
/// Increases the set capacity to the specified amount.
///
/// Does nothing if `capacity` is less than or equal to the current value.
pub fn grow(&mut self, capacity: usize) {
self.reads_and_writes.grow(capacity);
self.writes.grow(capacity);
}
/// Adds access to the element given by `index`.
pub fn add_read(&mut self, index: T) {
self.reads_and_writes.grow(index.sparse_set_index() + 1);
self.reads_and_writes.insert(index.sparse_set_index());
self.reads_and_writes
.grow_and_insert(index.sparse_set_index());
}
/// Adds exclusive access to the element given by `index`.
pub fn add_write(&mut self, index: T) {
self.reads_and_writes.grow(index.sparse_set_index() + 1);
self.reads_and_writes.insert(index.sparse_set_index());
self.writes.grow(index.sparse_set_index() + 1);
self.writes.insert(index.sparse_set_index());
self.reads_and_writes
.grow_and_insert(index.sparse_set_index());
self.writes.grow_and_insert(index.sparse_set_index());
}
/// Adds an archetypal (indirect) access to the element given by `index`.
@ -128,8 +119,7 @@ impl<T: SparseSetIndex> Access<T> {
///
/// [`Has<T>`]: crate::query::Has
pub fn add_archetypal(&mut self, index: T) {
self.archetypal.grow(index.sparse_set_index() + 1);
self.archetypal.insert(index.sparse_set_index());
self.archetypal.grow_and_insert(index.sparse_set_index());
}
/// Returns `true` if this can access the element given by `index`.
@ -389,9 +379,7 @@ impl<T: SparseSetIndex> FilteredAccess<T> {
}
fn add_required(&mut self, index: T) {
let index = index.sparse_set_index();
self.required.grow(index + 1);
self.required.insert(index);
self.required.grow_and_insert(index.sparse_set_index());
}
/// Adds a `With` filter: corresponds to a conjunction (AND) operation.
@ -399,10 +387,8 @@ impl<T: SparseSetIndex> FilteredAccess<T> {
/// Suppose we begin with `Or<(With<A>, With<B>)>`, which is represented by an array of two `AccessFilter` instances.
/// Adding `AND With<C>` via this method transforms it into the equivalent of `Or<((With<A>, With<C>), (With<B>, With<C>))>`.
pub fn and_with(&mut self, index: T) {
let index = index.sparse_set_index();
for filter in &mut self.filter_sets {
filter.with.grow(index + 1);
filter.with.insert(index);
filter.with.grow_and_insert(index.sparse_set_index());
}
}
@ -411,10 +397,8 @@ impl<T: SparseSetIndex> FilteredAccess<T> {
/// Suppose we begin with `Or<(With<A>, With<B>)>`, which is represented by an array of two `AccessFilter` instances.
/// Adding `AND Without<C>` via this method transforms it into the equivalent of `Or<((With<A>, Without<C>), (With<B>, Without<C>))>`.
pub fn and_without(&mut self, index: T) {
let index = index.sparse_set_index();
for filter in &mut self.filter_sets {
filter.without.grow(index + 1);
filter.without.insert(index);
filter.without.grow_and_insert(index.sparse_set_index());
}
}
@ -689,7 +673,6 @@ mod tests {
fn read_all_access_conflicts() {
// read_all / single write
let mut access_a = Access::<usize>::default();
access_a.grow(10);
access_a.add_write(0);
let mut access_b = Access::<usize>::default();
@ -699,7 +682,6 @@ mod tests {
// read_all / read_all
let mut access_a = Access::<usize>::default();
access_a.grow(10);
access_a.read_all();
let mut access_b = Access::<usize>::default();

View file

@ -312,14 +312,12 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
let archetype_index = archetype.id().index();
if !self.matched_archetypes.contains(archetype_index) {
self.matched_archetypes.grow(archetype_index + 1);
self.matched_archetypes.set(archetype_index, true);
self.matched_archetypes.grow_and_insert(archetype_index);
self.matched_archetype_ids.push(archetype.id());
}
let table_index = archetype.table_id().as_usize();
if !self.matched_tables.contains(table_index) {
self.matched_tables.grow(table_index + 1);
self.matched_tables.set(table_index, true);
self.matched_tables.grow_and_insert(table_index);
self.matched_table_ids.push(archetype.table_id());
}
}

View file

@ -35,7 +35,7 @@ bevy_derive = { path = "../bevy_derive", version = "0.14.0-dev" }
# other
bitflags = "2.3"
fixedbitset = "0.4"
fixedbitset = "0.5"
# direct dependency required for derive macro
bytemuck = { version = "1", features = ["derive"] }
radsort = "0.1"

View file

@ -30,7 +30,7 @@ bevy_derive = { path = "../bevy_derive", version = "0.14.0-dev" }
# other
bytemuck = { version = "1.5", features = ["derive"] }
fixedbitset = "0.4"
fixedbitset = "0.5"
guillotiere = "0.6.0"
thiserror = "1.0"
rectangle-pack = "0.4"