]> git.lizzy.rs Git - rust.git/blob - src/libcore/benches/iter.rs
Rollup merge of #57834 - SimonSapin:type_id, r=Centril
[rust.git] / src / libcore / benches / iter.rs
1 use core::iter::*;
2 use test::{Bencher, black_box};
3
4 #[bench]
5 fn bench_rposition(b: &mut Bencher) {
6     let it: Vec<usize> = (0..300).collect();
7     b.iter(|| {
8         it.iter().rposition(|&x| x <= 150);
9     });
10 }
11
12 #[bench]
13 fn bench_skip_while(b: &mut Bencher) {
14     b.iter(|| {
15         let it = 0..100;
16         let mut sum = 0;
17         it.skip_while(|&x| { sum += x; sum < 4000 }).all(|_| true);
18     });
19 }
20
21 #[bench]
22 fn bench_multiple_take(b: &mut Bencher) {
23     let mut it = (0..42).cycle();
24     b.iter(|| {
25         let n = it.next().unwrap();
26         for _ in 0..n {
27             it.clone().take(it.next().unwrap()).all(|_| true);
28         }
29     });
30 }
31
32 fn scatter(x: i32) -> i32 { (x * 31) % 127 }
33
34 #[bench]
35 fn bench_max_by_key(b: &mut Bencher) {
36     b.iter(|| {
37         let it = 0..100;
38         it.max_by_key(|&x| scatter(x))
39     })
40 }
41
42 // http://www.reddit.com/r/rust/comments/31syce/using_iterators_to_find_the_index_of_the_min_or/
43 #[bench]
44 fn bench_max_by_key2(b: &mut Bencher) {
45     fn max_index_iter(array: &[i32]) -> usize {
46         array.iter().enumerate().max_by_key(|&(_, item)| item).unwrap().0
47     }
48
49     let mut data = vec![0; 1638];
50     data[514] = 9999;
51
52     b.iter(|| max_index_iter(&data));
53 }
54
55 #[bench]
56 fn bench_max(b: &mut Bencher) {
57     b.iter(|| {
58         let it = 0..100;
59         it.map(scatter).max()
60     })
61 }
62
63 pub fn copy_zip(xs: &[u8], ys: &mut [u8]) {
64     for (a, b) in ys.iter_mut().zip(xs) {
65         *a = *b;
66     }
67 }
68
69 pub fn add_zip(xs: &[f32], ys: &mut [f32]) {
70     for (a, b) in ys.iter_mut().zip(xs) {
71         *a += *b;
72     }
73 }
74
75 #[bench]
76 fn bench_zip_copy(b: &mut Bencher) {
77     let source = vec![0u8; 16 * 1024];
78     let mut dst = black_box(vec![0u8; 16 * 1024]);
79     b.iter(|| {
80         copy_zip(&source, &mut dst)
81     })
82 }
83
84 #[bench]
85 fn bench_zip_add(b: &mut Bencher) {
86     let source = vec![1.; 16 * 1024];
87     let mut dst = vec![0.; 16 * 1024];
88     b.iter(|| {
89         add_zip(&source, &mut dst)
90     });
91 }
92
93 /// `Iterator::for_each` implemented as a plain loop.
94 fn for_each_loop<I, F>(iter: I, mut f: F) where
95     I: Iterator, F: FnMut(I::Item)
96 {
97     for item in iter {
98         f(item);
99     }
100 }
101
102 /// `Iterator::for_each` implemented with `fold` for internal iteration.
103 /// (except when `by_ref()` effectively disables that optimization.)
104 fn for_each_fold<I, F>(iter: I, mut f: F) where
105     I: Iterator, F: FnMut(I::Item)
106 {
107     iter.fold((), move |(), item| f(item));
108 }
109
110 #[bench]
111 fn bench_for_each_chain_loop(b: &mut Bencher) {
112     b.iter(|| {
113         let mut acc = 0;
114         let iter = (0i64..1000000).chain(0..1000000).map(black_box);
115         for_each_loop(iter, |x| acc += x);
116         acc
117     });
118 }
119
120 #[bench]
121 fn bench_for_each_chain_fold(b: &mut Bencher) {
122     b.iter(|| {
123         let mut acc = 0;
124         let iter = (0i64..1000000).chain(0..1000000).map(black_box);
125         for_each_fold(iter, |x| acc += x);
126         acc
127     });
128 }
129
130 #[bench]
131 fn bench_for_each_chain_ref_fold(b: &mut Bencher) {
132     b.iter(|| {
133         let mut acc = 0;
134         let mut iter = (0i64..1000000).chain(0..1000000).map(black_box);
135         for_each_fold(iter.by_ref(), |x| acc += x);
136         acc
137     });
138 }
139
140
141 /// Helper to benchmark `sum` for iterators taken by value which
142 /// can optimize `fold`, and by reference which cannot.
143 macro_rules! bench_sums {
144     ($bench_sum:ident, $bench_ref_sum:ident, $iter:expr) => {
145         #[bench]
146         fn $bench_sum(b: &mut Bencher) {
147             b.iter(|| -> i64 {
148                 $iter.map(black_box).sum()
149             });
150         }
151
152         #[bench]
153         fn $bench_ref_sum(b: &mut Bencher) {
154             b.iter(|| -> i64 {
155                 $iter.map(black_box).by_ref().sum()
156             });
157         }
158     }
159 }
160
161 bench_sums! {
162     bench_flat_map_sum,
163     bench_flat_map_ref_sum,
164     (0i64..1000).flat_map(|x| x..x+1000)
165 }
166
167 bench_sums! {
168     bench_flat_map_chain_sum,
169     bench_flat_map_chain_ref_sum,
170     (0i64..1000000).flat_map(|x| once(x).chain(once(x)))
171 }
172
173 bench_sums! {
174     bench_enumerate_sum,
175     bench_enumerate_ref_sum,
176     (0i64..1000000).enumerate().map(|(i, x)| x * i as i64)
177 }
178
179 bench_sums! {
180     bench_enumerate_chain_sum,
181     bench_enumerate_chain_ref_sum,
182     (0i64..1000000).chain(0..1000000).enumerate().map(|(i, x)| x * i as i64)
183 }
184
185 bench_sums! {
186     bench_filter_sum,
187     bench_filter_ref_sum,
188     (0i64..1000000).filter(|x| x % 2 == 0)
189 }
190
191 bench_sums! {
192     bench_filter_chain_sum,
193     bench_filter_chain_ref_sum,
194     (0i64..1000000).chain(0..1000000).filter(|x| x % 2 == 0)
195 }
196
197 bench_sums! {
198     bench_filter_map_sum,
199     bench_filter_map_ref_sum,
200     (0i64..1000000).filter_map(|x| x.checked_mul(x))
201 }
202
203 bench_sums! {
204     bench_filter_map_chain_sum,
205     bench_filter_map_chain_ref_sum,
206     (0i64..1000000).chain(0..1000000).filter_map(|x| x.checked_mul(x))
207 }
208
209 bench_sums! {
210     bench_fuse_sum,
211     bench_fuse_ref_sum,
212     (0i64..1000000).fuse()
213 }
214
215 bench_sums! {
216     bench_fuse_chain_sum,
217     bench_fuse_chain_ref_sum,
218     (0i64..1000000).chain(0..1000000).fuse()
219 }
220
221 bench_sums! {
222     bench_inspect_sum,
223     bench_inspect_ref_sum,
224     (0i64..1000000).inspect(|_| {})
225 }
226
227 bench_sums! {
228     bench_inspect_chain_sum,
229     bench_inspect_chain_ref_sum,
230     (0i64..1000000).chain(0..1000000).inspect(|_| {})
231 }
232
233 bench_sums! {
234     bench_peekable_sum,
235     bench_peekable_ref_sum,
236     (0i64..1000000).peekable()
237 }
238
239 bench_sums! {
240     bench_peekable_chain_sum,
241     bench_peekable_chain_ref_sum,
242     (0i64..1000000).chain(0..1000000).peekable()
243 }
244
245 bench_sums! {
246     bench_skip_sum,
247     bench_skip_ref_sum,
248     (0i64..1000000).skip(1000)
249 }
250
251 bench_sums! {
252     bench_skip_chain_sum,
253     bench_skip_chain_ref_sum,
254     (0i64..1000000).chain(0..1000000).skip(1000)
255 }
256
257 bench_sums! {
258     bench_skip_while_sum,
259     bench_skip_while_ref_sum,
260     (0i64..1000000).skip_while(|&x| x < 1000)
261 }
262
263 bench_sums! {
264     bench_skip_while_chain_sum,
265     bench_skip_while_chain_ref_sum,
266     (0i64..1000000).chain(0..1000000).skip_while(|&x| x < 1000)
267 }
268
269 bench_sums! {
270     bench_take_while_chain_sum,
271     bench_take_while_chain_ref_sum,
272     (0i64..1000000).chain(1000000..).take_while(|&x| x < 1111111)
273 }
274
275 bench_sums! {
276     bench_cycle_take_sum,
277     bench_cycle_take_ref_sum,
278     (0i64..10000).cycle().take(1000000)
279 }
280
281 // Checks whether Skip<Zip<A,B>> is as fast as Zip<Skip<A>, Skip<B>>, from
282 // https://users.rust-lang.org/t/performance-difference-between-iterator-zip-and-skip-order/15743
283 #[bench]
284 fn bench_zip_then_skip(b: &mut Bencher) {
285     let v: Vec<_> = (0..100_000).collect();
286     let t: Vec<_> = (0..100_000).collect();
287
288     b.iter(|| {
289         let s = v.iter().zip(t.iter()).skip(10000)
290             .take_while(|t| *t.0 < 10100)
291             .map(|(a, b)| *a + *b)
292             .sum::<u64>();
293         assert_eq!(s, 2009900);
294     });
295 }
296 #[bench]
297 fn bench_skip_then_zip(b: &mut Bencher) {
298     let v: Vec<_> = (0..100_000).collect();
299     let t: Vec<_> = (0..100_000).collect();
300
301     b.iter(|| {
302         let s = v.iter().skip(10000).zip(t.iter().skip(10000))
303             .take_while(|t| *t.0 < 10100)
304             .map(|(a, b)| *a + *b)
305             .sum::<u64>();
306         assert_eq!(s, 2009900);
307     });
308 }