Skip to content

Commit c3cff0a

Browse files
committed
VecDeque: improve performance for From<[T; N]>
Create VecDeque directly from the array instead of inserting items one-by-one.
1 parent 2ab73cf commit c3cff0a

File tree

2 files changed

+41
-1
lines changed

2 files changed

+41
-1
lines changed

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

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

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)