Skip to content

Commit

Permalink
Double the capacity of a full BlobVec after push
Browse files Browse the repository at this point in the history
  • Loading branch information
garychia committed Jan 2, 2024
1 parent 4034740 commit 38d595e
Showing 1 changed file with 16 additions and 5 deletions.
21 changes: 16 additions & 5 deletions crates/bevy_ecs/src/storage/blob_vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,17 @@ impl BlobVec {
}
}

/// Similar to `reserve_exact`. This method ensures that the capacity will grow at least `self.capacity()` if there is no
/// enough space to hold `additional` more elements.
pub fn reserve(&mut self, additional: usize) {
let available_space = self.capacity - self.len;
if available_space < additional && self.item_layout.size() > 0 {
let extra_space = self.capacity.max(additional - available_space);
let increment = unsafe { NonZeroUsize::new_unchecked(extra_space) };
unsafe { self.grow_exact(increment) };
}
}

// SAFETY: must not be called for a ZST item layout
#[warn(unsafe_op_in_unsafe_fn)] // to allow unsafe blocks in unsafe fn
unsafe fn grow_exact(&mut self, increment: NonZeroUsize) {
Expand Down Expand Up @@ -230,7 +241,7 @@ impl BlobVec {
/// The `value` must match the [`layout`](`BlobVec::layout`) of the elements in the [`BlobVec`].
#[inline]
pub unsafe fn push(&mut self, value: OwningPtr<'_>) {
self.reserve_exact(1);
self.reserve(1);
let index = self.len;
self.len += 1;
self.initialize_unchecked(index, value);
Expand Down Expand Up @@ -519,7 +530,7 @@ mod tests {
}

assert_eq!(blob_vec.len(), 1_000);
assert_eq!(blob_vec.capacity(), 1_000);
assert_eq!(blob_vec.capacity(), 1_024);
}

#[derive(Debug, Eq, PartialEq, Clone)]
Expand Down Expand Up @@ -579,19 +590,19 @@ mod tests {

push(&mut blob_vec, foo3.clone());
assert_eq!(blob_vec.len(), 3);
assert_eq!(blob_vec.capacity(), 3);
assert_eq!(blob_vec.capacity(), 4);

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

assert_eq!(blob_vec.len(), 2);
assert_eq!(blob_vec.capacity(), 3);
assert_eq!(blob_vec.capacity(), 4);

let value = swap_remove::<Foo>(&mut blob_vec, 0);
assert_eq!(foo1, value);
assert_eq!(blob_vec.len(), 1);
assert_eq!(blob_vec.capacity(), 3);
assert_eq!(blob_vec.capacity(), 4);

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

0 comments on commit 38d595e

Please sign in to comment.