Skip to content

Commit

Permalink
Increase by a minimum of x1.5 of existing capacity (uped to bin size)
Browse files Browse the repository at this point in the history
  • Loading branch information
dpc committed Sep 5, 2022
1 parent 98b0a6c commit d5690e4
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 4 deletions.
11 changes: 7 additions & 4 deletions library/alloc/src/raw_vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -396,8 +396,12 @@ impl<T, A: Allocator> RawVec<T, A> {

// Nothing we can really do about these checks, sadly.
let required_cap = len.checked_add(additional).ok_or(CapacityOverflow)?;
// The addition cannot overflow because `cap <= isize::MAX` and the type of `cap` is `usize`.
// By minimum we increase the cap by 1/2, which combined with rounding up
// to the next bin should result in rougly doubling (increase between x1.5, and x2.5).
let wanted_cap = cmp::max(self.cap + self.cap / 2, required_cap);

let cap = if let Some(alloc_size) = required_cap
let cap = if let Some(alloc_size) = wanted_cap
.checked_mul(mem::size_of::<T>())
.and_then(
// Add the overhead
Expand All @@ -419,9 +423,8 @@ impl<T, A: Allocator> RawVec<T, A> {
// Align the capacity to fit the bin
aligned_alloc_size / mem::size_of::<T>()
} else {
// Calculating alloc_size overflowed. Use old way to preserve behavior around overflows.
// The doubling cannot overflow because `cap <= isize::MAX` and the type of `cap` is `usize`.
cmp::max(self.cap * 2, required_cap)
// Calculating alloc_size overflowed. We just use `wanted_cap` to preserve behavior around cap `isize` overflows.
wanted_cap
};

let new_layout = Layout::array::<T>(cap);
Expand Down
9 changes: 9 additions & 0 deletions library/alloc/src/raw_vec/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,15 @@ fn grow_amortized_power_of_two_bins() {
assert_eq!(cap_for::<u8>(32), v.capacity());
}

{
let mut v: RawVec<u8> = RawVec::new();
v.reserve_exact(0, 6);
assert_eq!(6, v.capacity());
v.reserve(0, 8);
// increase all the way to 32 (instead of just 32), due to minimum capacity increase
assert_eq!(cap_for::<u8>(32), v.capacity());
}

{
let mut v: RawVec<[u8; 5]> = RawVec::new();
v.reserve(0, 1);
Expand Down

0 comments on commit d5690e4

Please sign in to comment.