Skip to content

Commit fe0759f

Browse files
authored
Rollup merge of rust-lang#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) ```
2 parents 7b1ad3e + c3cff0a commit fe0759f

File tree

3 files changed

+56
-1
lines changed

3 files changed

+56
-1
lines changed

library/alloc/benches/vec_deque.rs

+15
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,18 @@ fn bench_try_fold(b: &mut Bencher) {
5252

5353
b.iter(|| black_box(ring.iter().try_fold(0, |a, b| Some(a + b))))
5454
}
55+
56+
#[bench]
57+
fn bench_from_array_1000(b: &mut Bencher) {
58+
const N: usize = 1000;
59+
let mut array: [usize; N] = [0; N];
60+
61+
for i in 0..N {
62+
array[i] = i;
63+
}
64+
65+
b.iter(|| {
66+
let deq: VecDeque<_> = array.into();
67+
black_box(deq);
68+
})
69+
}

library/alloc/src/collections/vec_deque/mod.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -3004,6 +3004,16 @@ impl<T, const N: usize> From<[T; N]> for VecDeque<T> {
30043004
/// assert_eq!(deq1, deq2);
30053005
/// ```
30063006
fn from(arr: [T; N]) -> Self {
3007-
core::array::IntoIter::new(arr).collect()
3007+
let mut deq = VecDeque::with_capacity(N);
3008+
let arr = ManuallyDrop::new(arr);
3009+
if mem::size_of::<T>() != 0 {
3010+
// SAFETY: VecDeque::with_capacity ensures that there is enough capacity.
3011+
unsafe {
3012+
ptr::copy_nonoverlapping(arr.as_ptr(), deq.ptr(), N);
3013+
}
3014+
}
3015+
deq.tail = 0;
3016+
deq.head = N;
3017+
deq
30083018
}
30093019
}

library/alloc/src/collections/vec_deque/tests.rs

+30
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,36 @@ fn test_from_vec_zst_overflow() {
507507
assert_eq!(vd.len(), vec.len());
508508
}
509509

510+
#[test]
511+
fn test_from_array() {
512+
fn test<const N: usize>() {
513+
let mut array: [usize; N] = [0; N];
514+
515+
for i in 0..N {
516+
array[i] = i;
517+
}
518+
519+
let deq: VecDeque<_> = array.into();
520+
521+
for i in 0..N {
522+
assert_eq!(deq[i], i);
523+
}
524+
525+
assert!(deq.cap().is_power_of_two());
526+
assert_eq!(deq.len(), N);
527+
}
528+
test::<0>();
529+
test::<1>();
530+
test::<2>();
531+
test::<32>();
532+
test::<35>();
533+
534+
let array = [(); MAXIMUM_ZST_CAPACITY - 1];
535+
let deq = VecDeque::from(array);
536+
assert!(deq.cap().is_power_of_two());
537+
assert_eq!(deq.len(), MAXIMUM_ZST_CAPACITY - 1);
538+
}
539+
510540
#[test]
511541
fn test_vec_from_vecdeque() {
512542
use crate::vec::Vec;

0 commit comments

Comments
 (0)