1 #![feature(test)]
2
3 extern crate test;
4 #[macro_use]
5 extern crate lazy_static;
6
7 use fnv::FnvHasher;
8 use std::hash::BuildHasherDefault;
9 use std::hash::Hash;
10 type FnvBuilder = BuildHasherDefault<FnvHasher>;
11
12 use test::black_box;
13 use test::Bencher;
14
15 use indexmap::IndexMap;
16
17 use std::collections::HashMap;
18 use std::iter::FromIterator;
19
20 use rand::rngs::SmallRng;
21 use rand::seq::SliceRandom;
22 use rand::SeedableRng;
23
24 /// Use a consistently seeded Rng for benchmark stability
small_rng() -> SmallRng25 fn small_rng() -> SmallRng {
26 let seed = u64::from_le_bytes(*b"indexmap");
27 SmallRng::seed_from_u64(seed)
28 }
29
30 #[bench]
new_hashmap(b: &mut Bencher)31 fn new_hashmap(b: &mut Bencher) {
32 b.iter(|| HashMap::<String, String>::new());
33 }
34
35 #[bench]
new_indexmap(b: &mut Bencher)36 fn new_indexmap(b: &mut Bencher) {
37 b.iter(|| IndexMap::<String, String>::new());
38 }
39
40 #[bench]
with_capacity_10e5_hashmap(b: &mut Bencher)41 fn with_capacity_10e5_hashmap(b: &mut Bencher) {
42 b.iter(|| HashMap::<String, String>::with_capacity(10_000));
43 }
44
45 #[bench]
with_capacity_10e5_indexmap(b: &mut Bencher)46 fn with_capacity_10e5_indexmap(b: &mut Bencher) {
47 b.iter(|| IndexMap::<String, String>::with_capacity(10_000));
48 }
49
50 #[bench]
insert_hashmap_10_000(b: &mut Bencher)51 fn insert_hashmap_10_000(b: &mut Bencher) {
52 let c = 10_000;
53 b.iter(|| {
54 let mut map = HashMap::with_capacity(c);
55 for x in 0..c {
56 map.insert(x, ());
57 }
58 map
59 });
60 }
61
62 #[bench]
insert_indexmap_10_000(b: &mut Bencher)63 fn insert_indexmap_10_000(b: &mut Bencher) {
64 let c = 10_000;
65 b.iter(|| {
66 let mut map = IndexMap::with_capacity(c);
67 for x in 0..c {
68 map.insert(x, ());
69 }
70 map
71 });
72 }
73
74 #[bench]
insert_hashmap_string_10_000(b: &mut Bencher)75 fn insert_hashmap_string_10_000(b: &mut Bencher) {
76 let c = 10_000;
77 b.iter(|| {
78 let mut map = HashMap::with_capacity(c);
79 for x in 0..c {
80 map.insert(x.to_string(), ());
81 }
82 map
83 });
84 }
85
86 #[bench]
insert_indexmap_string_10_000(b: &mut Bencher)87 fn insert_indexmap_string_10_000(b: &mut Bencher) {
88 let c = 10_000;
89 b.iter(|| {
90 let mut map = IndexMap::with_capacity(c);
91 for x in 0..c {
92 map.insert(x.to_string(), ());
93 }
94 map
95 });
96 }
97
98 #[bench]
insert_hashmap_str_10_000(b: &mut Bencher)99 fn insert_hashmap_str_10_000(b: &mut Bencher) {
100 let c = 10_000;
101 let ss = Vec::from_iter((0..c).map(|x| x.to_string()));
102 b.iter(|| {
103 let mut map = HashMap::with_capacity(c);
104 for key in &ss {
105 map.insert(&key[..], ());
106 }
107 map
108 });
109 }
110
111 #[bench]
insert_indexmap_str_10_000(b: &mut Bencher)112 fn insert_indexmap_str_10_000(b: &mut Bencher) {
113 let c = 10_000;
114 let ss = Vec::from_iter((0..c).map(|x| x.to_string()));
115 b.iter(|| {
116 let mut map = IndexMap::with_capacity(c);
117 for key in &ss {
118 map.insert(&key[..], ());
119 }
120 map
121 });
122 }
123
124 #[bench]
insert_hashmap_int_bigvalue_10_000(b: &mut Bencher)125 fn insert_hashmap_int_bigvalue_10_000(b: &mut Bencher) {
126 let c = 10_000;
127 let value = [0u64; 10];
128 b.iter(|| {
129 let mut map = HashMap::with_capacity(c);
130 for i in 0..c {
131 map.insert(i, value);
132 }
133 map
134 });
135 }
136
137 #[bench]
insert_indexmap_int_bigvalue_10_000(b: &mut Bencher)138 fn insert_indexmap_int_bigvalue_10_000(b: &mut Bencher) {
139 let c = 10_000;
140 let value = [0u64; 10];
141 b.iter(|| {
142 let mut map = IndexMap::with_capacity(c);
143 for i in 0..c {
144 map.insert(i, value);
145 }
146 map
147 });
148 }
149
150 #[bench]
insert_hashmap_100_000(b: &mut Bencher)151 fn insert_hashmap_100_000(b: &mut Bencher) {
152 let c = 100_000;
153 b.iter(|| {
154 let mut map = HashMap::with_capacity(c);
155 for x in 0..c {
156 map.insert(x, ());
157 }
158 map
159 });
160 }
161
162 #[bench]
insert_indexmap_100_000(b: &mut Bencher)163 fn insert_indexmap_100_000(b: &mut Bencher) {
164 let c = 100_000;
165 b.iter(|| {
166 let mut map = IndexMap::with_capacity(c);
167 for x in 0..c {
168 map.insert(x, ());
169 }
170 map
171 });
172 }
173
174 #[bench]
insert_hashmap_150(b: &mut Bencher)175 fn insert_hashmap_150(b: &mut Bencher) {
176 let c = 150;
177 b.iter(|| {
178 let mut map = HashMap::with_capacity(c);
179 for x in 0..c {
180 map.insert(x, ());
181 }
182 map
183 });
184 }
185
186 #[bench]
insert_indexmap_150(b: &mut Bencher)187 fn insert_indexmap_150(b: &mut Bencher) {
188 let c = 150;
189 b.iter(|| {
190 let mut map = IndexMap::with_capacity(c);
191 for x in 0..c {
192 map.insert(x, ());
193 }
194 map
195 });
196 }
197
198 #[bench]
entry_hashmap_150(b: &mut Bencher)199 fn entry_hashmap_150(b: &mut Bencher) {
200 let c = 150;
201 b.iter(|| {
202 let mut map = HashMap::with_capacity(c);
203 for x in 0..c {
204 map.entry(x).or_insert(());
205 }
206 map
207 });
208 }
209
210 #[bench]
entry_indexmap_150(b: &mut Bencher)211 fn entry_indexmap_150(b: &mut Bencher) {
212 let c = 150;
213 b.iter(|| {
214 let mut map = IndexMap::with_capacity(c);
215 for x in 0..c {
216 map.entry(x).or_insert(());
217 }
218 map
219 });
220 }
221
222 #[bench]
iter_sum_hashmap_10_000(b: &mut Bencher)223 fn iter_sum_hashmap_10_000(b: &mut Bencher) {
224 let c = 10_000;
225 let mut map = HashMap::with_capacity(c);
226 let len = c - c / 10;
227 for x in 0..len {
228 map.insert(x, ());
229 }
230 assert_eq!(map.len(), len);
231 b.iter(|| map.keys().sum::<usize>());
232 }
233
234 #[bench]
iter_sum_indexmap_10_000(b: &mut Bencher)235 fn iter_sum_indexmap_10_000(b: &mut Bencher) {
236 let c = 10_000;
237 let mut map = IndexMap::with_capacity(c);
238 let len = c - c / 10;
239 for x in 0..len {
240 map.insert(x, ());
241 }
242 assert_eq!(map.len(), len);
243 b.iter(|| map.keys().sum::<usize>());
244 }
245
246 #[bench]
iter_black_box_hashmap_10_000(b: &mut Bencher)247 fn iter_black_box_hashmap_10_000(b: &mut Bencher) {
248 let c = 10_000;
249 let mut map = HashMap::with_capacity(c);
250 let len = c - c / 10;
251 for x in 0..len {
252 map.insert(x, ());
253 }
254 assert_eq!(map.len(), len);
255 b.iter(|| {
256 for &key in map.keys() {
257 black_box(key);
258 }
259 });
260 }
261
262 #[bench]
iter_black_box_indexmap_10_000(b: &mut Bencher)263 fn iter_black_box_indexmap_10_000(b: &mut Bencher) {
264 let c = 10_000;
265 let mut map = IndexMap::with_capacity(c);
266 let len = c - c / 10;
267 for x in 0..len {
268 map.insert(x, ());
269 }
270 assert_eq!(map.len(), len);
271 b.iter(|| {
272 for &key in map.keys() {
273 black_box(key);
274 }
275 });
276 }
277
shuffled_keys<I>(iter: I) -> Vec<I::Item> where I: IntoIterator,278 fn shuffled_keys<I>(iter: I) -> Vec<I::Item>
279 where
280 I: IntoIterator,
281 {
282 let mut v = Vec::from_iter(iter);
283 let mut rng = small_rng();
284 v.shuffle(&mut rng);
285 v
286 }
287
288 #[bench]
lookup_hashmap_10_000_exist(b: &mut Bencher)289 fn lookup_hashmap_10_000_exist(b: &mut Bencher) {
290 let c = 10_000;
291 let mut map = HashMap::with_capacity(c);
292 let keys = shuffled_keys(0..c);
293 for &key in &keys {
294 map.insert(key, 1);
295 }
296 b.iter(|| {
297 let mut found = 0;
298 for key in 5000..c {
299 found += map.get(&key).is_some() as i32;
300 }
301 found
302 });
303 }
304
305 #[bench]
lookup_hashmap_10_000_noexist(b: &mut Bencher)306 fn lookup_hashmap_10_000_noexist(b: &mut Bencher) {
307 let c = 10_000;
308 let mut map = HashMap::with_capacity(c);
309 let keys = shuffled_keys(0..c);
310 for &key in &keys {
311 map.insert(key, 1);
312 }
313 b.iter(|| {
314 let mut found = 0;
315 for key in c..15000 {
316 found += map.get(&key).is_some() as i32;
317 }
318 found
319 });
320 }
321
322 #[bench]
lookup_indexmap_10_000_exist(b: &mut Bencher)323 fn lookup_indexmap_10_000_exist(b: &mut Bencher) {
324 let c = 10_000;
325 let mut map = IndexMap::with_capacity(c);
326 let keys = shuffled_keys(0..c);
327 for &key in &keys {
328 map.insert(key, 1);
329 }
330 b.iter(|| {
331 let mut found = 0;
332 for key in 5000..c {
333 found += map.get(&key).is_some() as i32;
334 }
335 found
336 });
337 }
338
339 #[bench]
lookup_indexmap_10_000_noexist(b: &mut Bencher)340 fn lookup_indexmap_10_000_noexist(b: &mut Bencher) {
341 let c = 10_000;
342 let mut map = IndexMap::with_capacity(c);
343 let keys = shuffled_keys(0..c);
344 for &key in &keys {
345 map.insert(key, 1);
346 }
347 b.iter(|| {
348 let mut found = 0;
349 for key in c..15000 {
350 found += map.get(&key).is_some() as i32;
351 }
352 found
353 });
354 }
355
356 // number of items to look up
357 const LOOKUP_MAP_SIZE: u32 = 100_000_u32;
358 const LOOKUP_SAMPLE_SIZE: u32 = 5000;
359 const SORT_MAP_SIZE: usize = 10_000;
360
361 // use lazy_static so that comparison benchmarks use the exact same inputs
362 lazy_static! {
363 static ref KEYS: Vec<u32> = shuffled_keys(0..LOOKUP_MAP_SIZE);
364 }
365
366 lazy_static! {
367 static ref HMAP_100K: HashMap<u32, u32> = {
368 let c = LOOKUP_MAP_SIZE;
369 let mut map = HashMap::with_capacity(c as usize);
370 let keys = &*KEYS;
371 for &key in keys {
372 map.insert(key, key);
373 }
374 map
375 };
376 }
377
378 lazy_static! {
379 static ref IMAP_100K: IndexMap<u32, u32> = {
380 let c = LOOKUP_MAP_SIZE;
381 let mut map = IndexMap::with_capacity(c as usize);
382 let keys = &*KEYS;
383 for &key in keys {
384 map.insert(key, key);
385 }
386 map
387 };
388 }
389
390 lazy_static! {
391 static ref IMAP_SORT_U32: IndexMap<u32, u32> = {
392 let mut map = IndexMap::with_capacity(SORT_MAP_SIZE);
393 for &key in &KEYS[..SORT_MAP_SIZE] {
394 map.insert(key, key);
395 }
396 map
397 };
398 }
399 lazy_static! {
400 static ref IMAP_SORT_S: IndexMap<String, String> = {
401 let mut map = IndexMap::with_capacity(SORT_MAP_SIZE);
402 for &key in &KEYS[..SORT_MAP_SIZE] {
403 map.insert(format!("{:^16x}", &key), String::new());
404 }
405 map
406 };
407 }
408
409 #[bench]
lookup_hashmap_100_000_multi(b: &mut Bencher)410 fn lookup_hashmap_100_000_multi(b: &mut Bencher) {
411 let map = &*HMAP_100K;
412 b.iter(|| {
413 let mut found = 0;
414 for key in 0..LOOKUP_SAMPLE_SIZE {
415 found += map.get(&key).is_some() as u32;
416 }
417 found
418 });
419 }
420
421 #[bench]
lookup_indexmap_100_000_multi(b: &mut Bencher)422 fn lookup_indexmap_100_000_multi(b: &mut Bencher) {
423 let map = &*IMAP_100K;
424 b.iter(|| {
425 let mut found = 0;
426 for key in 0..LOOKUP_SAMPLE_SIZE {
427 found += map.get(&key).is_some() as u32;
428 }
429 found
430 });
431 }
432
433 // inorder: Test looking up keys in the same order as they were inserted
434 #[bench]
lookup_hashmap_100_000_inorder_multi(b: &mut Bencher)435 fn lookup_hashmap_100_000_inorder_multi(b: &mut Bencher) {
436 let map = &*HMAP_100K;
437 let keys = &*KEYS;
438 b.iter(|| {
439 let mut found = 0;
440 for key in &keys[0..LOOKUP_SAMPLE_SIZE as usize] {
441 found += map.get(key).is_some() as u32;
442 }
443 found
444 });
445 }
446
447 #[bench]
lookup_indexmap_100_000_inorder_multi(b: &mut Bencher)448 fn lookup_indexmap_100_000_inorder_multi(b: &mut Bencher) {
449 let map = &*IMAP_100K;
450 let keys = &*KEYS;
451 b.iter(|| {
452 let mut found = 0;
453 for key in &keys[0..LOOKUP_SAMPLE_SIZE as usize] {
454 found += map.get(key).is_some() as u32;
455 }
456 found
457 });
458 }
459
460 #[bench]
lookup_hashmap_100_000_single(b: &mut Bencher)461 fn lookup_hashmap_100_000_single(b: &mut Bencher) {
462 let map = &*HMAP_100K;
463 let mut iter = (0..LOOKUP_MAP_SIZE + LOOKUP_SAMPLE_SIZE).cycle();
464 b.iter(|| {
465 let key = iter.next().unwrap();
466 map.get(&key).is_some()
467 });
468 }
469
470 #[bench]
lookup_indexmap_100_000_single(b: &mut Bencher)471 fn lookup_indexmap_100_000_single(b: &mut Bencher) {
472 let map = &*IMAP_100K;
473 let mut iter = (0..LOOKUP_MAP_SIZE + LOOKUP_SAMPLE_SIZE).cycle();
474 b.iter(|| {
475 let key = iter.next().unwrap();
476 map.get(&key).is_some()
477 });
478 }
479
480 const GROW_SIZE: usize = 100_000;
481 type GrowKey = u32;
482
483 // Test grow/resize without preallocation
484 #[bench]
grow_fnv_hashmap_100_000(b: &mut Bencher)485 fn grow_fnv_hashmap_100_000(b: &mut Bencher) {
486 b.iter(|| {
487 let mut map: HashMap<_, _, FnvBuilder> = HashMap::default();
488 for x in 0..GROW_SIZE {
489 map.insert(x as GrowKey, x as GrowKey);
490 }
491 map
492 });
493 }
494
495 #[bench]
grow_fnv_indexmap_100_000(b: &mut Bencher)496 fn grow_fnv_indexmap_100_000(b: &mut Bencher) {
497 b.iter(|| {
498 let mut map: IndexMap<_, _, FnvBuilder> = IndexMap::default();
499 for x in 0..GROW_SIZE {
500 map.insert(x as GrowKey, x as GrowKey);
501 }
502 map
503 });
504 }
505
506 const MERGE: u64 = 10_000;
507 #[bench]
hashmap_merge_simple(b: &mut Bencher)508 fn hashmap_merge_simple(b: &mut Bencher) {
509 let first_map: HashMap<u64, _> = (0..MERGE).map(|i| (i, ())).collect();
510 let second_map: HashMap<u64, _> = (MERGE..MERGE * 2).map(|i| (i, ())).collect();
511 b.iter(|| {
512 let mut merged = first_map.clone();
513 merged.extend(second_map.iter().map(|(&k, &v)| (k, v)));
514 merged
515 });
516 }
517
518 #[bench]
hashmap_merge_shuffle(b: &mut Bencher)519 fn hashmap_merge_shuffle(b: &mut Bencher) {
520 let first_map: HashMap<u64, _> = (0..MERGE).map(|i| (i, ())).collect();
521 let second_map: HashMap<u64, _> = (MERGE..MERGE * 2).map(|i| (i, ())).collect();
522 let mut v = Vec::new();
523 let mut rng = small_rng();
524 b.iter(|| {
525 let mut merged = first_map.clone();
526 v.extend(second_map.iter().map(|(&k, &v)| (k, v)));
527 v.shuffle(&mut rng);
528 merged.extend(v.drain(..));
529
530 merged
531 });
532 }
533
534 #[bench]
indexmap_merge_simple(b: &mut Bencher)535 fn indexmap_merge_simple(b: &mut Bencher) {
536 let first_map: IndexMap<u64, _> = (0..MERGE).map(|i| (i, ())).collect();
537 let second_map: IndexMap<u64, _> = (MERGE..MERGE * 2).map(|i| (i, ())).collect();
538 b.iter(|| {
539 let mut merged = first_map.clone();
540 merged.extend(second_map.iter().map(|(&k, &v)| (k, v)));
541 merged
542 });
543 }
544
545 #[bench]
indexmap_merge_shuffle(b: &mut Bencher)546 fn indexmap_merge_shuffle(b: &mut Bencher) {
547 let first_map: IndexMap<u64, _> = (0..MERGE).map(|i| (i, ())).collect();
548 let second_map: IndexMap<u64, _> = (MERGE..MERGE * 2).map(|i| (i, ())).collect();
549 let mut v = Vec::new();
550 let mut rng = small_rng();
551 b.iter(|| {
552 let mut merged = first_map.clone();
553 v.extend(second_map.iter().map(|(&k, &v)| (k, v)));
554 v.shuffle(&mut rng);
555 merged.extend(v.drain(..));
556
557 merged
558 });
559 }
560
561 #[bench]
swap_remove_indexmap_100_000(b: &mut Bencher)562 fn swap_remove_indexmap_100_000(b: &mut Bencher) {
563 let map = IMAP_100K.clone();
564 let mut keys = Vec::from_iter(map.keys().copied());
565 let mut rng = small_rng();
566 keys.shuffle(&mut rng);
567
568 b.iter(|| {
569 let mut map = map.clone();
570 for key in &keys {
571 map.swap_remove(key);
572 }
573 assert_eq!(map.len(), 0);
574 map
575 });
576 }
577
578 #[bench]
shift_remove_indexmap_100_000_few(b: &mut Bencher)579 fn shift_remove_indexmap_100_000_few(b: &mut Bencher) {
580 let map = IMAP_100K.clone();
581 let mut keys = Vec::from_iter(map.keys().copied());
582 let mut rng = small_rng();
583 keys.shuffle(&mut rng);
584 keys.truncate(50);
585
586 b.iter(|| {
587 let mut map = map.clone();
588 for key in &keys {
589 map.shift_remove(key);
590 }
591 assert_eq!(map.len(), IMAP_100K.len() - keys.len());
592 map
593 });
594 }
595
596 #[bench]
shift_remove_indexmap_2_000_full(b: &mut Bencher)597 fn shift_remove_indexmap_2_000_full(b: &mut Bencher) {
598 let mut keys = KEYS[..2_000].to_vec();
599 let mut map = IndexMap::with_capacity(keys.len());
600 for &key in &keys {
601 map.insert(key, key);
602 }
603 let mut rng = small_rng();
604 keys.shuffle(&mut rng);
605
606 b.iter(|| {
607 let mut map = map.clone();
608 for key in &keys {
609 map.shift_remove(key);
610 }
611 assert_eq!(map.len(), 0);
612 map
613 });
614 }
615
616 #[bench]
pop_indexmap_100_000(b: &mut Bencher)617 fn pop_indexmap_100_000(b: &mut Bencher) {
618 let map = IMAP_100K.clone();
619
620 b.iter(|| {
621 let mut map = map.clone();
622 while !map.is_empty() {
623 map.pop();
624 }
625 assert_eq!(map.len(), 0);
626 map
627 });
628 }
629
630 #[bench]
few_retain_indexmap_100_000(b: &mut Bencher)631 fn few_retain_indexmap_100_000(b: &mut Bencher) {
632 let map = IMAP_100K.clone();
633
634 b.iter(|| {
635 let mut map = map.clone();
636 map.retain(|k, _| *k % 7 == 0);
637 map
638 });
639 }
640
641 #[bench]
few_retain_hashmap_100_000(b: &mut Bencher)642 fn few_retain_hashmap_100_000(b: &mut Bencher) {
643 let map = HMAP_100K.clone();
644
645 b.iter(|| {
646 let mut map = map.clone();
647 map.retain(|k, _| *k % 7 == 0);
648 map
649 });
650 }
651
652 #[bench]
half_retain_indexmap_100_000(b: &mut Bencher)653 fn half_retain_indexmap_100_000(b: &mut Bencher) {
654 let map = IMAP_100K.clone();
655
656 b.iter(|| {
657 let mut map = map.clone();
658 map.retain(|k, _| *k % 2 == 0);
659 map
660 });
661 }
662
663 #[bench]
half_retain_hashmap_100_000(b: &mut Bencher)664 fn half_retain_hashmap_100_000(b: &mut Bencher) {
665 let map = HMAP_100K.clone();
666
667 b.iter(|| {
668 let mut map = map.clone();
669 map.retain(|k, _| *k % 2 == 0);
670 map
671 });
672 }
673
674 #[bench]
many_retain_indexmap_100_000(b: &mut Bencher)675 fn many_retain_indexmap_100_000(b: &mut Bencher) {
676 let map = IMAP_100K.clone();
677
678 b.iter(|| {
679 let mut map = map.clone();
680 map.retain(|k, _| *k % 100 != 0);
681 map
682 });
683 }
684
685 #[bench]
many_retain_hashmap_100_000(b: &mut Bencher)686 fn many_retain_hashmap_100_000(b: &mut Bencher) {
687 let map = HMAP_100K.clone();
688
689 b.iter(|| {
690 let mut map = map.clone();
691 map.retain(|k, _| *k % 100 != 0);
692 map
693 });
694 }
695
696 // simple sort impl for comparison
simple_sort<K: Ord + Hash, V>(m: &mut IndexMap<K, V>)697 pub fn simple_sort<K: Ord + Hash, V>(m: &mut IndexMap<K, V>) {
698 let mut ordered: Vec<_> = m.drain(..).collect();
699 ordered.sort_by(|left, right| left.0.cmp(&right.0));
700 m.extend(ordered);
701 }
702
703 #[bench]
indexmap_sort_s(b: &mut Bencher)704 fn indexmap_sort_s(b: &mut Bencher) {
705 let map = IMAP_SORT_S.clone();
706
707 // there's a map clone there, but it's still useful to profile this
708 b.iter(|| {
709 let mut map = map.clone();
710 map.sort_keys();
711 map
712 });
713 }
714
715 #[bench]
indexmap_simple_sort_s(b: &mut Bencher)716 fn indexmap_simple_sort_s(b: &mut Bencher) {
717 let map = IMAP_SORT_S.clone();
718
719 // there's a map clone there, but it's still useful to profile this
720 b.iter(|| {
721 let mut map = map.clone();
722 simple_sort(&mut map);
723 map
724 });
725 }
726
727 #[bench]
indexmap_sort_u32(b: &mut Bencher)728 fn indexmap_sort_u32(b: &mut Bencher) {
729 let map = IMAP_SORT_U32.clone();
730
731 // there's a map clone there, but it's still useful to profile this
732 b.iter(|| {
733 let mut map = map.clone();
734 map.sort_keys();
735 map
736 });
737 }
738
739 #[bench]
indexmap_simple_sort_u32(b: &mut Bencher)740 fn indexmap_simple_sort_u32(b: &mut Bencher) {
741 let map = IMAP_SORT_U32.clone();
742
743 // there's a map clone there, but it's still useful to profile this
744 b.iter(|| {
745 let mut map = map.clone();
746 simple_sort(&mut map);
747 map
748 });
749 }
750
751 // measure the fixed overhead of cloning in sort benchmarks
752 #[bench]
indexmap_clone_for_sort_s(b: &mut Bencher)753 fn indexmap_clone_for_sort_s(b: &mut Bencher) {
754 let map = IMAP_SORT_S.clone();
755
756 b.iter(|| map.clone());
757 }
758
759 #[bench]
indexmap_clone_for_sort_u32(b: &mut Bencher)760 fn indexmap_clone_for_sort_u32(b: &mut Bencher) {
761 let map = IMAP_SORT_U32.clone();
762
763 b.iter(|| map.clone());
764 }
765