Skip to content

Commit 8ad1b93

Browse files
authored
Double the capacity when BlobVec is full (#11167)
# Objective - Fixes #10797 ## Solution - Double the capacity of a full `BlobVec` before pushing a new element.
1 parent eb07d16 commit 8ad1b93

File tree

1 file changed

+22
-5
lines changed

1 file changed

+22
-5
lines changed

crates/bevy_ecs/src/storage/blob_vec.rs

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,23 @@ impl BlobVec {
124124
}
125125
}
126126

127+
/// Reserves the minimum capacity for at least `additional` more elements to be inserted in the given `BlobVec`.
128+
#[inline]
129+
pub fn reserve(&mut self, additional: usize) {
130+
/// Similar to `reserve_exact`. This method ensures that the capacity will grow at least `self.capacity()` if there is no
131+
/// enough space to hold `additional` more elements.
132+
#[cold]
133+
fn do_reserve(slf: &mut BlobVec, additional: usize) {
134+
let increment = slf.capacity.max(additional - (slf.capacity - slf.len));
135+
let increment = NonZeroUsize::new(increment).unwrap();
136+
slf.grow_exact(increment);
137+
}
138+
139+
if self.capacity - self.len < additional {
140+
do_reserve(self, additional);
141+
}
142+
}
143+
127144
/// Grows the capacity by `increment` elements.
128145
///
129146
/// # Panics
@@ -241,7 +258,7 @@ impl BlobVec {
241258
/// The `value` must match the [`layout`](`BlobVec::layout`) of the elements in the [`BlobVec`].
242259
#[inline]
243260
pub unsafe fn push(&mut self, value: OwningPtr<'_>) {
244-
self.reserve_exact(1);
261+
self.reserve(1);
245262
let index = self.len;
246263
self.len += 1;
247264
self.initialize_unchecked(index, value);
@@ -530,7 +547,7 @@ mod tests {
530547
}
531548

532549
assert_eq!(blob_vec.len(), 1_000);
533-
assert_eq!(blob_vec.capacity(), 1_000);
550+
assert_eq!(blob_vec.capacity(), 1_024);
534551
}
535552

536553
#[derive(Debug, Eq, PartialEq, Clone)]
@@ -590,19 +607,19 @@ mod tests {
590607

591608
push(&mut blob_vec, foo3.clone());
592609
assert_eq!(blob_vec.len(), 3);
593-
assert_eq!(blob_vec.capacity(), 3);
610+
assert_eq!(blob_vec.capacity(), 4);
594611

595612
let last_index = blob_vec.len() - 1;
596613
let value = swap_remove::<Foo>(&mut blob_vec, last_index);
597614
assert_eq!(foo3, value);
598615

599616
assert_eq!(blob_vec.len(), 2);
600-
assert_eq!(blob_vec.capacity(), 3);
617+
assert_eq!(blob_vec.capacity(), 4);
601618

602619
let value = swap_remove::<Foo>(&mut blob_vec, 0);
603620
assert_eq!(foo1, value);
604621
assert_eq!(blob_vec.len(), 1);
605-
assert_eq!(blob_vec.capacity(), 3);
622+
assert_eq!(blob_vec.capacity(), 4);
606623

607624
foo2.a = 8;
608625
assert_eq!(get_mut::<Foo>(&mut blob_vec, 0), &foo2);

0 commit comments

Comments
 (0)