Rollup merge of #88452 - xu-cheng:vecdeque-from-array, r=m-ou-se

VecDeque: improve performance for From<[T; N]>

Create `VecDeque` directly from the array instead of inserting items one-by-one.

Benchmark
```
./x.py bench library/alloc --test-args vec_deque::bench_from_array_1000
```

* Before
```
test vec_deque::bench_from_array_1000                    ... bench:       3,991 ns/iter (+/- 717)
```

* After
```
test vec_deque::bench_from_array_1000                    ... bench:         268 ns/iter (+/- 37)
```
This commit is contained in:
Jubilee 2021-10-04 13:58:08 -07:00 committed by GitHub
commit 19d9a147be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 56 additions and 1 deletions

View File

@ -52,3 +52,18 @@ fn bench_try_fold(b: &mut Bencher) {
b.iter(|| black_box(ring.iter().try_fold(0, |a, b| Some(a + b))))
}
#[bench]
fn bench_from_array_1000(b: &mut Bencher) {
const N: usize = 1000;
let mut array: [usize; N] = [0; N];
for i in 0..N {
array[i] = i;
}
b.iter(|| {
let deq: VecDeque<_> = array.into();
black_box(deq);
})
}

View File

@ -3004,6 +3004,16 @@ impl<T, const N: usize> From<[T; N]> for VecDeque<T> {
/// assert_eq!(deq1, deq2);
/// ```
fn from(arr: [T; N]) -> Self {
core::array::IntoIter::new(arr).collect()
let mut deq = VecDeque::with_capacity(N);
let arr = ManuallyDrop::new(arr);
if mem::size_of::<T>() != 0 {
// SAFETY: VecDeque::with_capacity ensures that there is enough capacity.
unsafe {
ptr::copy_nonoverlapping(arr.as_ptr(), deq.ptr(), N);
}
}
deq.tail = 0;
deq.head = N;
deq
}
}

View File

@ -507,6 +507,36 @@ fn test_from_vec_zst_overflow() {
assert_eq!(vd.len(), vec.len());
}
#[test]
fn test_from_array() {
fn test<const N: usize>() {
let mut array: [usize; N] = [0; N];
for i in 0..N {
array[i] = i;
}
let deq: VecDeque<_> = array.into();
for i in 0..N {
assert_eq!(deq[i], i);
}
assert!(deq.cap().is_power_of_two());
assert_eq!(deq.len(), N);
}
test::<0>();
test::<1>();
test::<2>();
test::<32>();
test::<35>();
let array = [(); MAXIMUM_ZST_CAPACITY - 1];
let deq = VecDeque::from(array);
assert!(deq.cap().is_power_of_two());
assert_eq!(deq.len(), MAXIMUM_ZST_CAPACITY - 1);
}
#[test]
fn test_vec_from_vecdeque() {
use crate::vec::Vec;