Skip to content

Commit

Permalink
Rollup merge of #88452 - xu-cheng:vecdeque-from-array, r=m-ou-se
Browse files Browse the repository at this point in the history
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)
```
  • Loading branch information
workingjubilee committed Oct 4, 2021
2 parents a2c6075 + c3cff0a commit 19d9a14
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 1 deletion.
15 changes: 15 additions & 0 deletions library/alloc/benches/vec_deque.rs
Expand Up @@ -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);
})
}
12 changes: 11 additions & 1 deletion library/alloc/src/collections/vec_deque/mod.rs
Expand Up @@ -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
}
}
30 changes: 30 additions & 0 deletions library/alloc/src/collections/vec_deque/tests.rs
Expand Up @@ -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;
Expand Down

0 comments on commit 19d9a14

Please sign in to comment.