diff options
| author | Nicholas Nethercote <n.nethercote@gmail.com> | 2021-12-22 05:13:41 +1100 |
|---|---|---|
| committer | Nicholas Nethercote <n.nethercote@gmail.com> | 2021-12-22 05:13:41 +1100 |
| commit | 8217138f445e128f3bd4e4f517ac989d2abb621f (patch) | |
| tree | 9edcc44f958c5eb4f0d2fc1e93ddf6ddc761bdd5 | |
| parent | e95e084a14870a718c712936ab5a8f8cd0159485 (diff) | |
| download | rust-8217138f445e128f3bd4e4f517ac989d2abb621f.tar.gz rust-8217138f445e128f3bd4e4f517ac989d2abb621f.zip | |
RawVec: don't recompute capacity after allocating.
Currently it sets the capacity to `ptr.len() / mem::size_of::<T>()` after any buffer allocation/reallocation. This would be useful if allocators ever returned a `NonNull<[u8]>` with a size larger than requested. But this never happens, so it's not useful. Removing this slightly reduces the size of generated LLVM IR, and slightly speeds up the hot path of `RawVec` growth.
| -rw-r--r-- | library/alloc/src/raw_vec.rs | 35 |
1 files changed, 18 insertions, 17 deletions
diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index 3d38e73305a..3806bc546ee 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -190,9 +190,12 @@ impl<T, A: Allocator> RawVec<T, A> { Err(_) => handle_alloc_error(layout), }; + // Allocators currently return a `NonNull<[u8]>` whose length + // matches the size requested. If that ever changes, the capacity + // here should change to `ptr.len() / mem::size_of::<T>()`. Self { ptr: unsafe { Unique::new_unchecked(ptr.cast().as_ptr()) }, - cap: Self::capacity_from_bytes(ptr.len()), + cap: capacity, alloc, } } @@ -337,7 +340,7 @@ impl<T, A: Allocator> RawVec<T, A> { if self.needs_to_grow(len, additional) { self.grow_exact(len, additional) } else { Ok(()) } } - /// Shrinks the allocation down to the specified amount. If the given amount + /// Shrinks the buffer down to the specified capacity. If the given amount /// is 0, actually completely deallocates. /// /// # Panics @@ -348,8 +351,8 @@ impl<T, A: Allocator> RawVec<T, A> { /// /// Aborts on OOM. #[cfg(not(no_global_oom_handling))] - pub fn shrink_to_fit(&mut self, amount: usize) { - handle_reserve(self.shrink(amount)); + pub fn shrink_to_fit(&mut self, cap: usize) { + handle_reserve(self.shrink(cap)); } } @@ -360,14 +363,12 @@ impl<T, A: Allocator> RawVec<T, A> { additional > self.capacity().wrapping_sub(len) } - fn capacity_from_bytes(excess: usize) -> usize { - debug_assert_ne!(mem::size_of::<T>(), 0); - excess / mem::size_of::<T>() - } - - fn set_ptr(&mut self, ptr: NonNull<[u8]>) { + fn set_ptr_and_cap(&mut self, ptr: NonNull<[u8]>, cap: usize) { + // Allocators currently return a `NonNull<[u8]>` whose length matches + // the size requested. If that ever changes, the capacity here should + // change to `ptr.len() / mem::size_of::<T>()`. self.ptr = unsafe { Unique::new_unchecked(ptr.cast().as_ptr()) }; - self.cap = Self::capacity_from_bytes(ptr.len()); + self.cap = cap; } // This method is usually instantiated many times. So we want it to be as @@ -399,7 +400,7 @@ impl<T, A: Allocator> RawVec<T, A> { // `finish_grow` is non-generic over `T`. let ptr = finish_grow(new_layout, self.current_memory(), &mut self.alloc)?; - self.set_ptr(ptr); + self.set_ptr_and_cap(ptr, cap); Ok(()) } @@ -418,15 +419,15 @@ impl<T, A: Allocator> RawVec<T, A> { // `finish_grow` is non-generic over `T`. let ptr = finish_grow(new_layout, self.current_memory(), &mut self.alloc)?; - self.set_ptr(ptr); + self.set_ptr_and_cap(ptr, cap); Ok(()) } - fn shrink(&mut self, amount: usize) -> Result<(), TryReserveError> { - assert!(amount <= self.capacity(), "Tried to shrink to a larger capacity"); + fn shrink(&mut self, cap: usize) -> Result<(), TryReserveError> { + assert!(cap <= self.capacity(), "Tried to shrink to a larger capacity"); let (ptr, layout) = if let Some(mem) = self.current_memory() { mem } else { return Ok(()) }; - let new_size = amount * mem::size_of::<T>(); + let new_size = cap * mem::size_of::<T>(); let ptr = unsafe { let new_layout = Layout::from_size_align_unchecked(new_size, layout.align()); @@ -434,7 +435,7 @@ impl<T, A: Allocator> RawVec<T, A> { .shrink(ptr, layout, new_layout) .map_err(|_| AllocError { layout: new_layout, non_exhaustive: () })? }; - self.set_ptr(ptr); + self.set_ptr_and_cap(ptr, cap); Ok(()) } } |
