Skip to content

Commit ccba6c5

Browse files
committedJan 17, 2023
Add vec_deque::IntoIter benchmarks
1 parent 7c13b14 commit ccba6c5

File tree

1 file changed

+145
-1
lines changed

1 file changed

+145
-1
lines changed
 

‎library/alloc/benches/vec_deque.rs

+145-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
use std::collections::VecDeque;
1+
use core::iter::Iterator;
2+
use std::{
3+
collections::{vec_deque, VecDeque},
4+
mem,
5+
};
26
use test::{black_box, Bencher};
37

48
#[bench]
@@ -53,6 +57,146 @@ fn bench_try_fold(b: &mut Bencher) {
5357
b.iter(|| black_box(ring.iter().try_fold(0, |a, b| Some(a + b))))
5458
}
5559

60+
/// does the memory bookkeeping to reuse the buffer of the Vec between iterations.
61+
/// `setup` must not modify its argument's length or capacity. `g` must not move out of its argument.
62+
fn into_iter_helper<
63+
T: Copy,
64+
F: FnOnce(&mut VecDeque<T>),
65+
G: FnOnce(&mut vec_deque::IntoIter<T>),
66+
>(
67+
v: &mut Vec<T>,
68+
setup: F,
69+
g: G,
70+
) {
71+
let ptr = v.as_mut_ptr();
72+
let len = v.len();
73+
// ensure that the vec is full, to make sure that any wrapping from the deque doesn't
74+
// access uninitialized memory.
75+
assert_eq!(v.len(), v.capacity());
76+
77+
let mut deque = VecDeque::from(mem::take(v));
78+
setup(&mut deque);
79+
80+
let mut it = deque.into_iter();
81+
g(&mut it);
82+
83+
mem::forget(it);
84+
85+
// SAFETY: the provided functions are not allowed to modify the allocation, so the buffer is still alive.
86+
// len and capacity are accurate due to the above assertion.
87+
// All the elements in the buffer are still valid, because of `T: Copy` which implies `T: !Drop`.
88+
mem::forget(mem::replace(v, unsafe { Vec::from_raw_parts(ptr, len, len) }));
89+
}
90+
91+
#[bench]
92+
fn bench_into_iter(b: &mut Bencher) {
93+
let len = 1024;
94+
// we reuse this allocation for every run
95+
let mut vec: Vec<usize> = (0..len).collect();
96+
vec.shrink_to_fit();
97+
98+
b.iter(|| {
99+
let mut sum = 0;
100+
into_iter_helper(
101+
&mut vec,
102+
|_| {},
103+
|it| {
104+
for i in it {
105+
sum += i;
106+
}
107+
},
108+
);
109+
black_box(sum);
110+
111+
let mut sum = 0;
112+
// rotating a full deque doesn't move any memory.
113+
into_iter_helper(
114+
&mut vec,
115+
|d| d.rotate_left(len / 2),
116+
|it| {
117+
for i in it {
118+
sum += i;
119+
}
120+
},
121+
);
122+
black_box(sum);
123+
});
124+
}
125+
126+
#[bench]
127+
fn bench_into_iter_fold(b: &mut Bencher) {
128+
let len = 1024;
129+
130+
// because `fold` takes ownership of the iterator,
131+
// we can't prevent it from dropping the memory,
132+
// so we have to bite the bullet and reallocate
133+
// for every iteration.
134+
b.iter(|| {
135+
let deque: VecDeque<usize> = (0..len).collect();
136+
assert_eq!(deque.len(), deque.capacity());
137+
let sum = deque.into_iter().fold(0, |a, b| a + b);
138+
black_box(sum);
139+
140+
// rotating a full deque doesn't move any memory.
141+
let mut deque: VecDeque<usize> = (0..len).collect();
142+
assert_eq!(deque.len(), deque.capacity());
143+
deque.rotate_left(len / 2);
144+
let sum = deque.into_iter().fold(0, |a, b| a + b);
145+
black_box(sum);
146+
});
147+
}
148+
149+
#[bench]
150+
fn bench_into_iter_try_fold(b: &mut Bencher) {
151+
let len = 1024;
152+
// we reuse this allocation for every run
153+
let mut vec: Vec<usize> = (0..len).collect();
154+
vec.shrink_to_fit();
155+
156+
// Iterator::any uses Iterator::try_fold under the hood
157+
b.iter(|| {
158+
let mut b = false;
159+
into_iter_helper(&mut vec, |_| {}, |it| b = it.any(|i| i == len - 1));
160+
black_box(b);
161+
162+
into_iter_helper(&mut vec, |d| d.rotate_left(len / 2), |it| b = it.any(|i| i == len - 1));
163+
black_box(b);
164+
});
165+
}
166+
167+
#[bench]
168+
fn bench_into_iter_next_chunk(b: &mut Bencher) {
169+
let len = 1024;
170+
// we reuse this allocation for every run
171+
let mut vec: Vec<usize> = (0..len).collect();
172+
vec.shrink_to_fit();
173+
174+
b.iter(|| {
175+
let mut buf = [0; 64];
176+
into_iter_helper(
177+
&mut vec,
178+
|_| {},
179+
|it| {
180+
while let Ok(a) = it.next_chunk() {
181+
buf = a;
182+
}
183+
},
184+
);
185+
black_box(buf);
186+
187+
into_iter_helper(
188+
&mut vec,
189+
|d| d.rotate_left(len / 2),
190+
|it| {
191+
while let Ok(a) = it.next_chunk() {
192+
buf = a;
193+
}
194+
},
195+
);
196+
black_box(buf);
197+
});
198+
}
199+
56200
#[bench]
57201
fn bench_from_array_1000(b: &mut Bencher) {
58202
const N: usize = 1000;

0 commit comments

Comments
 (0)
Please sign in to comment.