|
12 | 12 |
|
13 | 13 | use prelude::*;
|
14 | 14 | use uint;
|
15 |
| -use util::{swap, replace}; |
| 15 | +use util::replace; |
16 | 16 | use vec;
|
17 | 17 |
|
18 | 18 | // FIXME: #5244: need to manually update the TrieNode constructor
|
@@ -415,39 +415,41 @@ fn find_mut<'r, T>(child: &'r mut Child<T>, key: uint, idx: uint) -> Option<&'r
|
415 | 415 |
|
416 | 416 | fn insert<T>(count: &mut uint, child: &mut Child<T>, key: uint, value: T,
|
417 | 417 | idx: uint) -> Option<T> {
|
418 |
| - let mut tmp = Nothing; |
419 |
| - let ret; |
420 |
| - swap(&mut tmp, child); |
421 |
| - |
422 |
| - *child = match tmp { |
423 |
| - External(stored_key, stored_value) => { |
424 |
| - if stored_key == key { |
425 |
| - ret = Some(stored_value); |
426 |
| - External(stored_key, value) |
427 |
| - } else { |
428 |
| - // conflict - split the node |
429 |
| - let mut new = ~TrieNode::new(); |
430 |
| - insert(&mut new.count, |
431 |
| - &mut new.children[chunk(stored_key, idx)], |
432 |
| - stored_key, stored_value, idx + 1); |
433 |
| - ret = insert(&mut new.count, &mut new.children[chunk(key, idx)], |
434 |
| - key, value, idx + 1); |
435 |
| - Internal(new) |
436 |
| - } |
437 |
| - } |
438 |
| - Internal(x) => { |
439 |
| - let mut x = x; |
440 |
| - ret = insert(&mut x.count, &mut x.children[chunk(key, idx)], key, |
441 |
| - value, idx + 1); |
442 |
| - Internal(x) |
443 |
| - } |
444 |
| - Nothing => { |
445 |
| - *count += 1; |
446 |
| - ret = None; |
447 |
| - External(key, value) |
448 |
| - } |
449 |
| - }; |
450 |
| - return ret; |
| 418 | + // we branch twice to avoid having to do the `replace` when we |
| 419 | + // don't need to; this is much faster, especially for keys that |
| 420 | + // have long shared prefixes. |
| 421 | + match *child { |
| 422 | + Nothing => { |
| 423 | + *count += 1; |
| 424 | + *child = External(key, value); |
| 425 | + return None; |
| 426 | + } |
| 427 | + Internal(ref mut x) => { |
| 428 | + return insert(&mut x.count, &mut x.children[chunk(key, idx)], key, value, idx + 1); |
| 429 | + } |
| 430 | + External(stored_key, ref mut stored_value) if stored_key == key => { |
| 431 | + // swap in the new value and return the old. |
| 432 | + return Some(replace(stored_value, value)); |
| 433 | + } |
| 434 | + _ => {} |
| 435 | + } |
| 436 | + |
| 437 | + // conflict, an external node with differing keys: we have to |
| 438 | + // split the node, so we need the old value by value; hence we |
| 439 | + // have to move out of `child`. |
| 440 | + match replace(child, Nothing) { |
| 441 | + External(stored_key, stored_value) => { |
| 442 | + let mut new = ~TrieNode::new(); |
| 443 | + insert(&mut new.count, |
| 444 | + &mut new.children[chunk(stored_key, idx)], |
| 445 | + stored_key, stored_value, idx + 1); |
| 446 | + let ret = insert(&mut new.count, &mut new.children[chunk(key, idx)], |
| 447 | + key, value, idx + 1); |
| 448 | + *child = Internal(new); |
| 449 | + return ret; |
| 450 | + } |
| 451 | + _ => unreachable!() |
| 452 | + } |
451 | 453 | }
|
452 | 454 |
|
453 | 455 | fn remove<T>(count: &mut uint, child: &mut Child<T>, key: uint,
|
@@ -886,6 +888,54 @@ mod bench_map {
|
886 | 888 | }
|
887 | 889 | });
|
888 | 890 | }
|
| 891 | + |
| 892 | + #[bench] |
| 893 | + fn bench_insert_large(bh: &mut BenchHarness) { |
| 894 | + let mut m = TrieMap::<[uint, .. 10]>::new(); |
| 895 | + let mut rng = weak_rng(); |
| 896 | + |
| 897 | + bh.iter(|| { |
| 898 | + for _ in range(0, 1000) { |
| 899 | + m.insert(rng.gen(), [1, .. 10]); |
| 900 | + } |
| 901 | + }) |
| 902 | + } |
| 903 | + #[bench] |
| 904 | + fn bench_insert_large_low_bits(bh: &mut BenchHarness) { |
| 905 | + let mut m = TrieMap::<[uint, .. 10]>::new(); |
| 906 | + let mut rng = weak_rng(); |
| 907 | + |
| 908 | + bh.iter(|| { |
| 909 | + for _ in range(0, 1000) { |
| 910 | + // only have the last few bits set. |
| 911 | + m.insert(rng.gen::<uint>() & 0xff_ff, [1, .. 10]); |
| 912 | + } |
| 913 | + }) |
| 914 | + } |
| 915 | + |
| 916 | + #[bench] |
| 917 | + fn bench_insert_small(bh: &mut BenchHarness) { |
| 918 | + let mut m = TrieMap::<()>::new(); |
| 919 | + let mut rng = weak_rng(); |
| 920 | + |
| 921 | + bh.iter(|| { |
| 922 | + for _ in range(0, 1000) { |
| 923 | + m.insert(rng.gen(), ()); |
| 924 | + } |
| 925 | + }) |
| 926 | + } |
| 927 | + #[bench] |
| 928 | + fn bench_insert_small_low_bits(bh: &mut BenchHarness) { |
| 929 | + let mut m = TrieMap::<()>::new(); |
| 930 | + let mut rng = weak_rng(); |
| 931 | + |
| 932 | + bh.iter(|| { |
| 933 | + for _ in range(0, 1000) { |
| 934 | + // only have the last few bits set. |
| 935 | + m.insert(rng.gen::<uint>() & 0xff_ff, ()); |
| 936 | + } |
| 937 | + }) |
| 938 | + } |
889 | 939 | }
|
890 | 940 |
|
891 | 941 | #[cfg(test)]
|
|
0 commit comments