@@ -69,7 +69,24 @@ pub struct RawVec<'a, T> {
69
69
a : & ' a Bump ,
70
70
}
71
71
72
+ // Tiny Vecs are dumb. Skip to:
73
+ // - 8 if the element size is 1, because any heap allocators is likely
74
+ // to round up a request of less than 8 bytes to at least 8 bytes.
75
+ // - 4 if elements are moderate-sized (<= 1 KiB).
76
+ // - 1 otherwise, to avoid wasting too much space for very short Vecs.
77
+ const fn min_non_zero_cap ( size : usize ) -> usize {
78
+ if size == 1 {
79
+ 8
80
+ } else if size <= 1024 {
81
+ 4
82
+ } else {
83
+ 1
84
+ }
85
+ }
86
+
72
87
impl < ' a , T > RawVec < ' a , T > {
88
+ pub ( crate ) const MIN_NON_ZERO_CAP : usize = min_non_zero_cap ( size_of :: < T > ( ) ) ;
89
+
73
90
/// Like `new` but parameterized over the choice of allocator for
74
91
/// the returned RawVec.
75
92
pub fn new_in ( a : & ' a Bump ) -> Self {
@@ -351,22 +368,6 @@ impl<'a, T> RawVec<'a, T> {
351
368
}
352
369
}
353
370
354
- /// Calculates the buffer's new size given that it'll hold `len +
355
- /// additional` elements. This logic is used in amortized reserve methods.
356
- /// Returns `(new_capacity, new_alloc_size)`.
357
- fn amortized_new_size (
358
- & self ,
359
- len : usize ,
360
- additional : usize ,
361
- ) -> Result < usize , CollectionAllocErr > {
362
- // Nothing we can really do about these checks :(
363
- let required_cap = len. checked_add ( additional) . ok_or ( CapacityOverflow ) ?;
364
- // Cannot overflow, because `cap <= isize::MAX`, and type of `cap` is `usize`.
365
- let double_cap = self . cap * 2 ;
366
- // `double_cap` guarantees exponential growth.
367
- Ok ( cmp:: max ( double_cap, required_cap) )
368
- }
369
-
370
371
/// The same as `reserve`, but returns on errors instead of panicking or aborting.
371
372
pub fn try_reserve ( & mut self , len : usize , additional : usize ) -> Result < ( ) , CollectionAllocErr > {
372
373
if self . needs_to_grow ( len, additional) {
@@ -620,12 +621,19 @@ impl<'a, T> RawVec<'a, T> {
620
621
// If we make it past the first branch then we are guaranteed to
621
622
// panic.
622
623
623
- let new_cap = self . amortized_new_size ( len, additional) ?;
624
- let new_layout = Layout :: array :: < T > ( new_cap) . map_err ( |_| CapacityOverflow ) ?;
624
+ // Nothing we can really do about these checks, sadly.
625
+ let required_cap = len. checked_add ( additional) . ok_or ( CapacityOverflow ) ?;
626
+
627
+ // This guarantees exponential growth. The doubling cannot overflow
628
+ // because `cap <= isize::MAX` and the type of `cap` is `usize`.
629
+ let cap = cmp:: max ( self . cap ( ) * 2 , required_cap) ;
630
+ let cap = cmp:: max ( Self :: MIN_NON_ZERO_CAP , cap) ;
631
+
632
+ let new_layout = Layout :: array :: < T > ( cap) . map_err ( |_| CapacityOverflow ) ?;
625
633
626
634
self . ptr = self . finish_grow ( new_layout) ?. cast ( ) ;
627
635
628
- self . cap = new_cap ;
636
+ self . cap = cap ;
629
637
630
638
Ok ( ( ) )
631
639
}
0 commit comments