3 use rand::distributions::{Alphanumeric, Standard};
4 use rand::{thread_rng, Rng, SeedableRng};
5 use rand_xorshift::XorShiftRng;
6 use test::{black_box, Bencher};
9 fn iterator(b: &mut Bencher) {
10 // peculiar numbers to stop LLVM from optimising the summation
12 let v: Vec<_> = (0..100).map(|i| i ^ (i << 1) ^ (i >> 1)).collect();
19 // sum == 11806, to stop dead code elimination.
27 fn mut_iterator(b: &mut Bencher) {
28 let mut v = vec![0; 100];
40 fn concat(b: &mut Bencher) {
41 let xss: Vec<Vec<i32>> = (0..100).map(|i| (0..i).collect()).collect();
48 fn join(b: &mut Bencher) {
49 let xss: Vec<Vec<i32>> = (0..100).map(|i| (0..i).collect()).collect();
50 b.iter(|| xss.join(&0));
54 fn push(b: &mut Bencher) {
55 let mut vec = Vec::<i32>::new();
63 fn starts_with_same_vector(b: &mut Bencher) {
64 let vec: Vec<_> = (0..100).collect();
65 b.iter(|| vec.starts_with(&vec))
69 fn starts_with_single_element(b: &mut Bencher) {
70 let vec: Vec<_> = vec![0];
71 b.iter(|| vec.starts_with(&vec))
75 fn starts_with_diff_one_element_at_end(b: &mut Bencher) {
76 let vec: Vec<_> = (0..100).collect();
77 let mut match_vec: Vec<_> = (0..99).collect();
79 b.iter(|| vec.starts_with(&match_vec))
83 fn ends_with_same_vector(b: &mut Bencher) {
84 let vec: Vec<_> = (0..100).collect();
85 b.iter(|| vec.ends_with(&vec))
89 fn ends_with_single_element(b: &mut Bencher) {
90 let vec: Vec<_> = vec![0];
91 b.iter(|| vec.ends_with(&vec))
95 fn ends_with_diff_one_element_at_beginning(b: &mut Bencher) {
96 let vec: Vec<_> = (0..100).collect();
97 let mut match_vec: Vec<_> = (0..100).collect();
99 b.iter(|| vec.starts_with(&match_vec))
103 fn contains_last_element(b: &mut Bencher) {
104 let vec: Vec<_> = (0..100).collect();
105 b.iter(|| vec.contains(&99))
109 fn zero_1kb_from_elem(b: &mut Bencher) {
110 b.iter(|| vec![0u8; 1024]);
114 fn zero_1kb_set_memory(b: &mut Bencher) {
116 let mut v = Vec::<u8>::with_capacity(1024);
118 let vp = v.as_mut_ptr();
119 ptr::write_bytes(vp, 0, 1024);
127 fn zero_1kb_loop_set(b: &mut Bencher) {
129 let mut v = Vec::<u8>::with_capacity(1024);
140 fn zero_1kb_mut_iter(b: &mut Bencher) {
142 let mut v = Vec::<u8>::with_capacity(1024);
154 fn random_inserts(b: &mut Bencher) {
155 let mut rng = thread_rng();
157 let mut v = vec![(0, 0); 30];
160 v.insert(rng.gen::<usize>() % (l + 1), (1, 1));
166 fn random_removes(b: &mut Bencher) {
167 let mut rng = thread_rng();
169 let mut v = vec![(0, 0); 130];
172 v.remove(rng.gen::<usize>() % l);
177 fn gen_ascending(len: usize) -> Vec<u64> {
178 (0..len as u64).collect()
181 fn gen_descending(len: usize) -> Vec<u64> {
182 (0..len as u64).rev().collect()
185 const SEED: [u8; 16] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
187 fn gen_random(len: usize) -> Vec<u64> {
188 let mut rng = XorShiftRng::from_seed(SEED);
189 (&mut rng).sample_iter(&Standard).take(len).collect()
192 fn gen_random_bytes(len: usize) -> Vec<u8> {
193 let mut rng = XorShiftRng::from_seed(SEED);
194 (&mut rng).sample_iter(&Standard).take(len).collect()
197 fn gen_mostly_ascending(len: usize) -> Vec<u64> {
198 let mut rng = XorShiftRng::from_seed(SEED);
199 let mut v = gen_ascending(len);
200 for _ in (0usize..).take_while(|x| x * x <= len) {
201 let x = rng.gen::<usize>() % len;
202 let y = rng.gen::<usize>() % len;
208 fn gen_mostly_descending(len: usize) -> Vec<u64> {
209 let mut rng = XorShiftRng::from_seed(SEED);
210 let mut v = gen_descending(len);
211 for _ in (0usize..).take_while(|x| x * x <= len) {
212 let x = rng.gen::<usize>() % len;
213 let y = rng.gen::<usize>() % len;
219 fn gen_strings(len: usize) -> Vec<String> {
220 let mut rng = XorShiftRng::from_seed(SEED);
223 let n = rng.gen::<usize>() % 20 + 1;
224 v.push((&mut rng).sample_iter(&Alphanumeric).take(n).collect());
229 fn gen_big_random(len: usize) -> Vec<[u64; 16]> {
230 let mut rng = XorShiftRng::from_seed(SEED);
231 (&mut rng).sample_iter(&Standard).map(|x| [x; 16]).take(len).collect()
235 ($f:ident, $name:ident, $gen:expr, $len:expr) => {
237 fn $name(b: &mut Bencher) {
239 b.iter(|| v.clone().$f());
240 b.bytes = $len * mem::size_of_val(&$gen(1)[0]) as u64;
245 macro_rules! sort_strings {
246 ($f:ident, $name:ident, $gen:expr, $len:expr) => {
248 fn $name(b: &mut Bencher) {
250 let v = v.iter().map(|s| &**s).collect::<Vec<&str>>();
251 b.iter(|| v.clone().$f());
252 b.bytes = $len * mem::size_of::<&str>() as u64;
257 macro_rules! sort_expensive {
258 ($f:ident, $name:ident, $gen:expr, $len:expr) => {
260 fn $name(b: &mut Bencher) {
263 let mut v = v.clone();
265 v.$f(|a: &u64, b: &u64| {
267 if count % 1_000_000_000 == 0 {
268 panic!("should not happen");
270 (*a as f64).cos().partial_cmp(&(*b as f64).cos()).unwrap()
274 b.bytes = $len * mem::size_of_val(&$gen(1)[0]) as u64;
279 macro_rules! sort_lexicographic {
280 ($f:ident, $name:ident, $gen:expr, $len:expr) => {
282 fn $name(b: &mut Bencher) {
284 b.iter(|| v.clone().$f(|x| x.to_string()));
285 b.bytes = $len * mem::size_of_val(&$gen(1)[0]) as u64;
290 sort!(sort, sort_small_ascending, gen_ascending, 10);
291 sort!(sort, sort_small_descending, gen_descending, 10);
292 sort!(sort, sort_small_random, gen_random, 10);
293 sort!(sort, sort_small_big, gen_big_random, 10);
294 sort!(sort, sort_medium_random, gen_random, 100);
295 sort!(sort, sort_large_ascending, gen_ascending, 10000);
296 sort!(sort, sort_large_descending, gen_descending, 10000);
297 sort!(sort, sort_large_mostly_ascending, gen_mostly_ascending, 10000);
298 sort!(sort, sort_large_mostly_descending, gen_mostly_descending, 10000);
299 sort!(sort, sort_large_random, gen_random, 10000);
300 sort!(sort, sort_large_big, gen_big_random, 10000);
301 sort_strings!(sort, sort_large_strings, gen_strings, 10000);
302 sort_expensive!(sort_by, sort_large_expensive, gen_random, 10000);
304 sort!(sort_unstable, sort_unstable_small_ascending, gen_ascending, 10);
305 sort!(sort_unstable, sort_unstable_small_descending, gen_descending, 10);
306 sort!(sort_unstable, sort_unstable_small_random, gen_random, 10);
307 sort!(sort_unstable, sort_unstable_small_big, gen_big_random, 10);
308 sort!(sort_unstable, sort_unstable_medium_random, gen_random, 100);
309 sort!(sort_unstable, sort_unstable_large_ascending, gen_ascending, 10000);
310 sort!(sort_unstable, sort_unstable_large_descending, gen_descending, 10000);
311 sort!(sort_unstable, sort_unstable_large_mostly_ascending, gen_mostly_ascending, 10000);
312 sort!(sort_unstable, sort_unstable_large_mostly_descending, gen_mostly_descending, 10000);
313 sort!(sort_unstable, sort_unstable_large_random, gen_random, 10000);
314 sort!(sort_unstable, sort_unstable_large_big, gen_big_random, 10000);
315 sort_strings!(sort_unstable, sort_unstable_large_strings, gen_strings, 10000);
316 sort_expensive!(sort_unstable_by, sort_unstable_large_expensive, gen_random, 10000);
318 sort_lexicographic!(sort_by_key, sort_by_key_lexicographic, gen_random, 10000);
319 sort_lexicographic!(sort_unstable_by_key, sort_unstable_by_key_lexicographic, gen_random, 10000);
320 sort_lexicographic!(sort_by_cached_key, sort_by_cached_key_lexicographic, gen_random, 10000);
322 macro_rules! reverse {
323 ($name:ident, $ty:ty, $f:expr) => {
325 fn $name(b: &mut Bencher) {
326 // odd length and offset by 1 to be as unaligned as possible
328 let mut v: Vec<_> = (0..1 + (n / mem::size_of::<$ty>() as u64)).map($f).collect();
329 b.iter(|| black_box(&mut v[1..]).reverse());
335 reverse!(reverse_u8, u8, |x| x as u8);
336 reverse!(reverse_u16, u16, |x| x as u16);
337 reverse!(reverse_u8x3, [u8; 3], |x| [x as u8, (x >> 8) as u8, (x >> 16) as u8]);
338 reverse!(reverse_u32, u32, |x| x as u32);
339 reverse!(reverse_u64, u64, |x| x as u64);
340 reverse!(reverse_u128, u128, |x| x as u128);
342 struct F64x4(f64, f64, f64, f64);
343 reverse!(reverse_simd_f64x4, F64x4, |x| {
348 macro_rules! rotate {
349 ($name:ident, $gen:expr, $len:expr, $mid:expr) => {
351 fn $name(b: &mut Bencher) {
352 let size = mem::size_of_val(&$gen(1)[0]);
353 let mut v = $gen($len * 8 / size);
354 b.iter(|| black_box(&mut v).rotate_left(($mid * 8 + size - 1) / size));
355 b.bytes = (v.len() * size) as u64;
360 rotate!(rotate_tiny_by1, gen_random, 16, 1);
361 rotate!(rotate_tiny_half, gen_random, 16, 16 / 2);
362 rotate!(rotate_tiny_half_plus_one, gen_random, 16, 16 / 2 + 1);
364 rotate!(rotate_medium_by1, gen_random, 9158, 1);
365 rotate!(rotate_medium_by727_u64, gen_random, 9158, 727);
366 rotate!(rotate_medium_by727_bytes, gen_random_bytes, 9158, 727);
367 rotate!(rotate_medium_by727_strings, gen_strings, 9158, 727);
368 rotate!(rotate_medium_half, gen_random, 9158, 9158 / 2);
369 rotate!(rotate_medium_half_plus_one, gen_random, 9158, 9158 / 2 + 1);
371 // Intended to use more RAM than the machine has cache
372 rotate!(rotate_huge_by1, gen_random, 5 * 1024 * 1024, 1);
373 rotate!(rotate_huge_by9199_u64, gen_random, 5 * 1024 * 1024, 9199);
374 rotate!(rotate_huge_by9199_bytes, gen_random_bytes, 5 * 1024 * 1024, 9199);
375 rotate!(rotate_huge_by9199_strings, gen_strings, 5 * 1024 * 1024, 9199);
376 rotate!(rotate_huge_by9199_big, gen_big_random, 5 * 1024 * 1024, 9199);
377 rotate!(rotate_huge_by1234577_u64, gen_random, 5 * 1024 * 1024, 1234577);
378 rotate!(rotate_huge_by1234577_bytes, gen_random_bytes, 5 * 1024 * 1024, 1234577);
379 rotate!(rotate_huge_by1234577_strings, gen_strings, 5 * 1024 * 1024, 1234577);
380 rotate!(rotate_huge_by1234577_big, gen_big_random, 5 * 1024 * 1024, 1234577);
381 rotate!(rotate_huge_half, gen_random, 5 * 1024 * 1024, 5 * 1024 * 1024 / 2);
382 rotate!(rotate_huge_half_plus_one, gen_random, 5 * 1024 * 1024, 5 * 1024 * 1024 / 2 + 1);