Skip to content

Commit cdb62af

Browse files
committed
Replace ComponentSparseSet's internals with a Column (#4909)
# Objective Following #4855, `Column` is just a parallel `BlobVec`/`Vec<UnsafeCell<ComponentTicks>>` pair, which is identical to the dense and ticks vecs in `ComponentSparseSet`, which has some code duplication with `Column`. ## Solution Replace dense and ticks in `ComponentSparseSet` with a `Column`.
1 parent f2b5450 commit cdb62af

File tree

2 files changed

+14
-30
lines changed

2 files changed

+14
-30
lines changed

crates/bevy_ecs/src/storage/sparse_set.rs

Lines changed: 13 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::{
22
component::{ComponentId, ComponentInfo, ComponentTicks},
33
entity::Entity,
4-
storage::BlobVec,
4+
storage::Column,
55
};
66
use bevy_ptr::{OwningPtr, Ptr};
77
use std::{cell::UnsafeCell, hash::Hash, marker::PhantomData};
@@ -96,8 +96,7 @@ impl<I: SparseSetIndex, V> SparseArray<I, V> {
9696
/// Designed for relatively fast insertions and deletions.
9797
#[derive(Debug)]
9898
pub struct ComponentSparseSet {
99-
dense: BlobVec,
100-
ticks: Vec<UnsafeCell<ComponentTicks>>,
99+
dense: Column,
101100
// Internally this only relies on the Entity ID to keep track of where the component data is
102101
// stored for entities that are alive. The generation is not required, but is stored
103102
// in debug builds to validate that access is correct.
@@ -111,19 +110,14 @@ pub struct ComponentSparseSet {
111110
impl ComponentSparseSet {
112111
pub fn new(component_info: &ComponentInfo, capacity: usize) -> Self {
113112
Self {
114-
// SAFE: component_info.drop() is compatible with the items that will be inserted.
115-
dense: unsafe {
116-
BlobVec::new(component_info.layout(), component_info.drop(), capacity)
117-
},
118-
ticks: Vec::with_capacity(capacity),
113+
dense: Column::with_capacity(component_info, capacity),
119114
entities: Vec::with_capacity(capacity),
120115
sparse: Default::default(),
121116
}
122117
}
123118

124119
pub fn clear(&mut self) {
125120
self.dense.clear();
126-
self.ticks.clear();
127121
self.entities.clear();
128122
self.sparse.clear();
129123
}
@@ -148,20 +142,13 @@ impl ComponentSparseSet {
148142
if let Some(&dense_index) = self.sparse.get(entity.id()) {
149143
#[cfg(debug_assertions)]
150144
assert_eq!(entity, self.entities[dense_index as usize]);
151-
let _entity = self.dense.replace_unchecked(dense_index as usize, value);
152-
*self.ticks.get_unchecked_mut(dense_index as usize) =
153-
UnsafeCell::new(ComponentTicks::new(change_tick));
145+
self.dense.replace(dense_index as usize, value, change_tick);
154146
} else {
155147
let dense_index = self.dense.len();
156-
self.dense.push(value);
148+
self.dense.push(value, ComponentTicks::new(change_tick));
157149
self.sparse.insert(entity.id(), dense_index as u32);
158150
#[cfg(debug_assertions)]
159-
{
160-
assert_eq!(self.ticks.len(), dense_index);
161-
assert_eq!(self.entities.len(), dense_index);
162-
}
163-
self.ticks
164-
.push(UnsafeCell::new(ComponentTicks::new(change_tick)));
151+
assert_eq!(self.entities.len(), dense_index);
165152
#[cfg(not(debug_assertions))]
166153
self.entities.push(entity.id());
167154
#[cfg(debug_assertions)]
@@ -192,7 +179,7 @@ impl ComponentSparseSet {
192179
#[cfg(debug_assertions)]
193180
assert_eq!(entity, self.entities[dense_index]);
194181
// SAFE: if the sparse index points to something in the dense vec, it exists
195-
unsafe { self.dense.get_unchecked(dense_index) }
182+
unsafe { self.dense.get_data_unchecked(dense_index) }
196183
})
197184
}
198185

@@ -204,8 +191,8 @@ impl ComponentSparseSet {
204191
// SAFE: if the sparse index points to something in the dense vec, it exists
205192
unsafe {
206193
Some((
207-
self.dense.get_unchecked(dense_index),
208-
self.ticks.get_unchecked(dense_index),
194+
self.dense.get_data_unchecked(dense_index),
195+
self.dense.get_ticks_unchecked(dense_index),
209196
))
210197
}
211198
}
@@ -216,7 +203,7 @@ impl ComponentSparseSet {
216203
#[cfg(debug_assertions)]
217204
assert_eq!(entity, self.entities[dense_index]);
218205
// SAFE: if the sparse index points to something in the dense vec, it exists
219-
unsafe { Some(self.ticks.get_unchecked(dense_index)) }
206+
unsafe { Some(self.dense.get_ticks_unchecked(dense_index)) }
220207
}
221208

222209
/// Removes the `entity` from this sparse set and returns a pointer to the associated value (if
@@ -227,11 +214,10 @@ impl ComponentSparseSet {
227214
let dense_index = dense_index as usize;
228215
#[cfg(debug_assertions)]
229216
assert_eq!(entity, self.entities[dense_index]);
230-
self.ticks.swap_remove(dense_index);
231217
self.entities.swap_remove(dense_index);
232218
let is_last = dense_index == self.dense.len() - 1;
233219
// SAFE: dense_index was just removed from `sparse`, which ensures that it is valid
234-
let value = unsafe { self.dense.swap_remove_and_forget_unchecked(dense_index) };
220+
let (value, _) = unsafe { self.dense.swap_remove_and_forget_unchecked(dense_index) };
235221
if !is_last {
236222
let swapped_entity = self.entities[dense_index];
237223
#[cfg(not(debug_assertions))]
@@ -249,11 +235,10 @@ impl ComponentSparseSet {
249235
let dense_index = dense_index as usize;
250236
#[cfg(debug_assertions)]
251237
assert_eq!(entity, self.entities[dense_index]);
252-
self.ticks.swap_remove(dense_index);
253238
self.entities.swap_remove(dense_index);
254239
let is_last = dense_index == self.dense.len() - 1;
255240
// SAFE: if the sparse index points to something in the dense vec, it exists
256-
unsafe { self.dense.swap_remove_and_drop_unchecked(dense_index) }
241+
unsafe { self.dense.swap_remove_unchecked(dense_index) }
257242
if !is_last {
258243
let swapped_entity = self.entities[dense_index];
259244
#[cfg(not(debug_assertions))]
@@ -269,9 +254,7 @@ impl ComponentSparseSet {
269254
}
270255

271256
pub(crate) fn check_change_ticks(&mut self, change_tick: u32) {
272-
for component_ticks in &mut self.ticks {
273-
component_ticks.get_mut().check_ticks(change_tick);
274-
}
257+
self.dense.check_change_ticks(change_tick);
275258
}
276259
}
277260

crates/bevy_ecs/src/storage/table.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ impl TableId {
3030
}
3131
}
3232

33+
#[derive(Debug)]
3334
pub struct Column {
3435
pub(crate) data: BlobVec,
3536
pub(crate) ticks: Vec<UnsafeCell<ComponentTicks>>,

0 commit comments

Comments
 (0)