diff options
| author | Jubilee <46493976+workingjubilee@users.noreply.github.com> | 2021-10-04 13:58:08 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-10-04 13:58:08 -0700 |
| commit | 19d9a147bef8dfaf5c718c0cb4008accd86e7a5e (patch) | |
| tree | 267098e6b130065344aacf2d9f744cd27ead12a5 | |
| parent | a2c6075dfff58626afc9ab57c2c6b284c5612ec7 (diff) | |
| parent | c3cff0a75412f18971a325640a5dd7bd67b28972 (diff) | |
| download | rust-19d9a147bef8dfaf5c718c0cb4008accd86e7a5e.tar.gz rust-19d9a147bef8dfaf5c718c0cb4008accd86e7a5e.zip | |
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) ```
| -rw-r--r-- | library/alloc/benches/vec_deque.rs | 15 | ||||
| -rw-r--r-- | library/alloc/src/collections/vec_deque/mod.rs | 12 | ||||
| -rw-r--r-- | library/alloc/src/collections/vec_deque/tests.rs | 30 |
3 files changed, 56 insertions, 1 deletions
diff --git a/library/alloc/benches/vec_deque.rs b/library/alloc/benches/vec_deque.rs index bf2dffd1e93..404cfa6addb 100644 --- a/library/alloc/benches/vec_deque.rs +++ b/library/alloc/benches/vec_deque.rs @@ -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); + }) +} diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 4a2b0b33bf2..007548ad1ab 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -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 } } diff --git a/library/alloc/src/collections/vec_deque/tests.rs b/library/alloc/src/collections/vec_deque/tests.rs index 56257e43462..2be83f68f01 100644 --- a/library/alloc/src/collections/vec_deque/tests.rs +++ b/library/alloc/src/collections/vec_deque/tests.rs @@ -508,6 +508,36 @@ fn test_from_vec_zst_overflow() { } #[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; |
