@@ -2784,6 +2784,51 @@ impl<T, I: SliceIndex<[T]>, A: Allocator> IndexMut<I> for Vec<T, A> {
2784
2784
}
2785
2785
}
2786
2786
2787
+ /// Collects an iterator into a Vec, commonly called via [`Iterator::collect()`]
2788
+ ///
2789
+ /// # Allocation behavior
2790
+ ///
2791
+ /// In general `Vec` does not guarantee any particular grow/allocation stategy.
2792
+ /// That also applies to this trait impl.
2793
+ ///
2794
+ /// **Note:** This section covers implementation details and is therefore exempt from
2795
+ /// stability guarantees.
2796
+ ///
2797
+ /// Vec may use any or none of the following strategies,
2798
+ /// depending on the supplied iterator:
2799
+ ///
2800
+ /// * preallocate based on [`Iterator::size_hint()`]
2801
+ /// * and panic if the number of items is not outside the provided lower/upper bounds
2802
+ /// * use an amortized growth strategy similar to `pushing` one item at a time
2803
+ /// * perform the iteration in-place on the original allocation backing the iterator
2804
+ ///
2805
+ /// The last case warrants some attention. It is an optimization that in many cases reduces peak memory
2806
+ /// consumption and improves cache locality. But when a large number of big, short-lived
2807
+ /// allocations are created, only a small fraction of their items gets collected, no further use
2808
+ /// is made of the spare capacity and the resulting `Vec` is moved into a longer-lived structure
2809
+ /// this can lead to the large allocations having their lifetimes unnecessarily extended which
2810
+ /// can result in increased memory footprint.
2811
+ ///
2812
+ /// In cases where this is an issue the excess capacity can be discard with [`Vec::shrink_to()`],
2813
+ /// [`Vec::shrink_to_fit()`] or by collecting into [`Box<[T]>`][owned slice] instead which additionally reduces
2814
+ /// the size of the longlived struct.
2815
+ ///
2816
+ /// [owned slice]: Box
2817
+ ///
2818
+ /// ```rust
2819
+ /// # use std::sync::Mutex;
2820
+ /// static LONG_LIVED: Mutex<Vec<Vec<u16>>> = Mutex::new(Vec::new());
2821
+ ///
2822
+ /// // many short-lived allocations
2823
+ /// for i in 0..100 {
2824
+ /// let big_temporary: Vec<u16> = (0..1024).collect();
2825
+ /// // discard most items
2826
+ /// let mut result: Vec<_> = big_temporary.into_iter().filter(|i| i % 100 == 0).collect();
2827
+ /// // without this a lot of unused capacity might be moved into the global
2828
+ /// result.shrink_to_fit();
2829
+ /// LONG_LIVED.lock().unwrap().push(result);
2830
+ /// }
2831
+ /// ```
2787
2832
#[ cfg( not( no_global_oom_handling) ) ]
2788
2833
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
2789
2834
impl < T > FromIterator < T > for Vec < T > {
0 commit comments