Skip to content

Commit eb8fa80

Browse files
committed
test and bench BTree query API
1 parent 6214e28 commit eb8fa80

File tree

3 files changed

+263
-17
lines changed

3 files changed

+263
-17
lines changed

src/libcollectionstest/bench.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ macro_rules! map_insert_seq_bench {
6262
}
6363

6464
macro_rules! map_find_rand_bench {
65-
($name: ident, $n: expr, $map: ident) => (
65+
($name: ident, $n: expr, $map: ident, $lookup: ident) => (
6666
#[bench]
6767
pub fn $name(b: &mut ::test::Bencher) {
6868
use std::iter::Iterator;
@@ -86,7 +86,7 @@ macro_rules! map_find_rand_bench {
8686
// measure
8787
let mut i = 0;
8888
b.iter(|| {
89-
let t = map.get(&keys[i]);
89+
let t = $lookup(&map, &keys[i]);
9090
i = (i + 1) % n;
9191
black_box(t);
9292
})
@@ -95,7 +95,7 @@ macro_rules! map_find_rand_bench {
9595
}
9696

9797
macro_rules! map_find_seq_bench {
98-
($name: ident, $n: expr, $map: ident) => (
98+
($name: ident, $n: expr, $map: ident, $lookup: ident) => (
9999
#[bench]
100100
pub fn $name(b: &mut ::test::Bencher) {
101101
use test::black_box;
@@ -111,7 +111,7 @@ macro_rules! map_find_seq_bench {
111111
// measure
112112
let mut i = 0;
113113
b.iter(|| {
114-
let x = map.get(&i);
114+
let x = $lookup(&map, &i);
115115
i = (i + 1) % n;
116116
black_box(x);
117117
})

src/libcollectionstest/btree/map.rs

Lines changed: 253 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,81 @@ fn test_basic_small() {
7575
assert_eq!(map.remove(&1), None);
7676
}
7777

78+
#[test]
79+
fn test_query() {
80+
// NOTE: shouldn't need to test mutable variants because they're
81+
// generated from the same template and deviate only in mutability
82+
// annotations. However incorrect implementations *may* result from Node's
83+
// mut and non-mut impls drifting.
84+
85+
let size = 10000;
86+
let gap = 4;
87+
let min = gap;
88+
let max = (size - 1) * gap;
89+
90+
let mut map = BTreeMap::new();
91+
92+
assert_eq!(map.min(), None);
93+
assert_eq!(map.max(), None);
94+
assert_eq!(map.get_lt(&0), None);
95+
assert_eq!(map.get_gt(&0), None);
96+
assert_eq!(map.get_le(&0), None);
97+
assert_eq!(map.get_ge(&0), None);
98+
99+
// linear insertions make degenerate trees, but we shouldn't care since all
100+
// large trees are structurally similar for these tests.
101+
for i in 1 .. size {
102+
// times 10 to make gaps
103+
map.insert(i * gap, i * gap);
104+
}
105+
106+
assert_eq!(map.min(), Some((&min, &min)));
107+
assert_eq!(map.max(), Some((&max, &max)));
108+
109+
110+
// less exists checks
111+
for i in min + 1 .. max + gap {
112+
// gap = 4
113+
// input: 5 6 7 8 9 10 11 12
114+
// <= 4 4 4 8 8 8 8 12
115+
// < 4 4 4 4 8 8 8 8
116+
let le = i / gap * gap;
117+
let lt = (i - 1) / gap * gap;
118+
assert_eq!(map.get_lt(&i), Some((&lt, &lt)));
119+
assert_eq!(map.get_le(&i), Some((&le, &le)));
120+
}
121+
122+
// greater exists checks
123+
for i in min - gap .. max - 1 {
124+
// gap = 4
125+
// input: 4 5 6 7 8 9 10 11
126+
// >= 4 8 8 8 8 12 12 12 (same as < but +4)
127+
// > 8 8 8 8 12 12 12 12 (same as <= but +4)
128+
let ge = (i - 1) / gap * gap + gap;
129+
let gt = i / gap * gap + gap;
130+
assert_eq!(map.get_gt(&i), Some((&gt, &gt)));
131+
assert_eq!(map.get_ge(&i), Some((&ge, &ge)));
132+
}
133+
134+
// less doesn't exist checks
135+
for i in 0 .. min {
136+
assert_eq!(map.get_lt(&i), None);
137+
assert_eq!(map.get_le(&i), None);
138+
}
139+
140+
// greater doesn't exist checks
141+
for i in max + 1 .. max + gap {
142+
assert_eq!(map.get_gt(&i), None);
143+
assert_eq!(map.get_ge(&i), None);
144+
}
145+
146+
// special cases:
147+
assert_eq!(map.get_lt(&min), None);
148+
assert_eq!(map.get_le(&min), Some((&min, &min)));
149+
assert_eq!(map.get_gt(&max), None);
150+
assert_eq!(map.get_ge(&max), Some((&max, &max)));
151+
}
152+
78153
#[test]
79154
fn test_iter() {
80155
let size = 10000;
@@ -297,20 +372,121 @@ fn test_extend_ref() {
297372
mod bench {
298373
use std::collections::BTreeMap;
299374
use std::__rand::{Rng, thread_rng};
375+
use std::collections::Bound::{Included, Excluded, Unbounded};
300376

301377
use test::{Bencher, black_box};
302378

379+
fn get<'a, K: Ord, V>(map: &'a BTreeMap<K, V>, key: &K) -> Option<&'a V> {
380+
map.get(key)
381+
}
382+
383+
fn get_lt<'a, K: Ord, V>(map: &'a BTreeMap<K, V>, key: &K) -> Option<(&'a K, &'a V)> {
384+
map.get_lt(key)
385+
}
386+
fn get_le<'a, K: Ord, V>(map: &'a BTreeMap<K, V>, key: &K) -> Option<(&'a K, &'a V)> {
387+
map.get_le(key)
388+
}
389+
fn get_gt<'a, K: Ord, V>(map: &'a BTreeMap<K, V>, key: &K) -> Option<(&'a K, &'a V)> {
390+
map.get_gt(key)
391+
}
392+
fn get_ge<'a, K: Ord, V>(map: &'a BTreeMap<K, V>, key: &K) -> Option<(&'a K, &'a V)> {
393+
map.get_ge(key)
394+
}
395+
396+
fn get_lt_range<'a, K: Ord, V>(map: &'a BTreeMap<K, V>, key: &K) -> Option<(&'a K, &'a V)> {
397+
map.range(Unbounded, Excluded(key)).next_back()
398+
}
399+
fn get_le_range<'a, K: Ord, V>(map: &'a BTreeMap<K, V>, key: &K) -> Option<(&'a K, &'a V)> {
400+
map.range(Unbounded, Included(key)).next_back()
401+
}
402+
fn get_gt_range<'a, K: Ord, V>(map: &'a BTreeMap<K, V>, key: &K) -> Option<(&'a K, &'a V)> {
403+
map.range(Excluded(key), Unbounded).next()
404+
}
405+
fn get_ge_range<'a, K: Ord, V>(map: &'a BTreeMap<K, V>, key: &K) -> Option<(&'a K, &'a V)> {
406+
map.range(Included(key), Unbounded).next()
407+
}
408+
409+
303410
map_insert_rand_bench!{insert_rand_100, 100, BTreeMap}
304-
map_insert_rand_bench!{insert_rand_10_000, 10_000, BTreeMap}
411+
map_insert_rand_bench!{insert_rand_10000, 10_000, BTreeMap}
305412

306413
map_insert_seq_bench!{insert_seq_100, 100, BTreeMap}
307-
map_insert_seq_bench!{insert_seq_10_000, 10_000, BTreeMap}
414+
map_insert_seq_bench!{insert_seq_10000, 10_000, BTreeMap}
415+
416+
417+
418+
map_find_rand_bench!{get_rand_100_eq, 100, BTreeMap, get}
419+
map_find_rand_bench!{get_rand_10000_eq, 10_000, BTreeMap, get}
420+
421+
map_find_seq_bench!{get_seq_100_eq, 100, BTreeMap, get}
422+
map_find_seq_bench!{get_seq_10000_eq, 10_000, BTreeMap, get}
423+
424+
425+
426+
427+
map_find_rand_bench!{get_rand_100_lt, 100, BTreeMap, get_lt}
428+
map_find_rand_bench!{get_rand_10000_lt, 10_000, BTreeMap, get_lt}
429+
430+
map_find_seq_bench!{get_seq_100_lt, 100, BTreeMap, get_lt}
431+
map_find_seq_bench!{get_seq_10000_lt, 10_000, BTreeMap, get_lt}
432+
433+
434+
435+
map_find_rand_bench!{get_rand_100_le, 100, BTreeMap, get_le}
436+
map_find_rand_bench!{get_rand_10000_le, 10_000, BTreeMap, get_le}
437+
438+
map_find_seq_bench!{get_seq_100_le, 100, BTreeMap, get_le}
439+
map_find_seq_bench!{get_seq_10000_le, 10_000, BTreeMap, get_le}
440+
441+
442+
443+
map_find_rand_bench!{get_rand_100_gt, 100, BTreeMap, get_gt}
444+
map_find_rand_bench!{get_rand_10000_gt, 10_000, BTreeMap, get_gt}
445+
446+
map_find_seq_bench!{get_seq_100_gt, 100, BTreeMap, get_gt}
447+
map_find_seq_bench!{get_seq_10000_gt, 10_000, BTreeMap, get_gt}
448+
449+
450+
451+
map_find_rand_bench!{get_rand_100_ge, 100, BTreeMap, get_ge}
452+
map_find_rand_bench!{get_rand_10000_ge, 10_000, BTreeMap, get_ge}
453+
454+
map_find_seq_bench!{get_seq_100_ge, 100, BTreeMap, get_ge}
455+
map_find_seq_bench!{get_seq_10000_ge, 10_000, BTreeMap, get_ge}
456+
457+
458+
308459

309-
map_find_rand_bench!{find_rand_100, 100, BTreeMap}
310-
map_find_rand_bench!{find_rand_10_000, 10_000, BTreeMap}
460+
map_find_rand_bench!{get_rand_100_lt_range, 100, BTreeMap, get_lt_range}
461+
map_find_rand_bench!{get_rand_10000_lt_range, 10_000, BTreeMap, get_lt_range}
462+
463+
map_find_seq_bench!{get_seq_100_lt_range, 100, BTreeMap, get_lt_range}
464+
map_find_seq_bench!{get_seq_10000_lt_range, 10_000, BTreeMap, get_lt_range}
465+
466+
467+
468+
map_find_rand_bench!{get_rand_100_le_range, 100, BTreeMap, get_le_range}
469+
map_find_rand_bench!{get_rand_10000_le_range, 10_000, BTreeMap, get_le_range}
470+
471+
map_find_seq_bench!{get_seq_100_le_range, 100, BTreeMap, get_le_range}
472+
map_find_seq_bench!{get_seq_10000_le_range, 10_000, BTreeMap, get_le_range}
473+
474+
475+
476+
map_find_rand_bench!{get_rand_100_gt_range, 100, BTreeMap, get_gt_range}
477+
map_find_rand_bench!{get_rand_10000_gt_range, 10_000, BTreeMap, get_gt_range}
478+
479+
map_find_seq_bench!{get_seq_100_gt_range, 100, BTreeMap, get_gt_range}
480+
map_find_seq_bench!{get_seq_10000_gt_range, 10_000, BTreeMap, get_gt_range}
481+
482+
483+
484+
map_find_rand_bench!{get_rand_100_ge_range, 100, BTreeMap, get_ge_range}
485+
map_find_rand_bench!{get_rand_10000_ge_range, 10_000, BTreeMap, get_ge_range}
486+
487+
map_find_seq_bench!{get_seq_100_ge_range, 100, BTreeMap, get_ge_range}
488+
map_find_seq_bench!{get_seq_10000_ge_range, 10_000, BTreeMap, get_ge_range}
311489

312-
map_find_seq_bench!{find_seq_100, 100, BTreeMap}
313-
map_find_seq_bench!{find_seq_10_000, 10_000, BTreeMap}
314490

315491
fn bench_iter(b: &mut Bencher, size: i32) {
316492
let mut map = BTreeMap::<i32, i32>::new();
@@ -327,18 +503,86 @@ mod bench {
327503
});
328504
}
329505

506+
fn bench_iter_with_queries_forward(b: &mut Bencher, size: i32) {
507+
let mut map = BTreeMap::<i32, i32>::new();
508+
let mut rng = thread_rng();
509+
510+
for _ in 0..size {
511+
map.insert(rng.gen(), rng.gen());
512+
}
513+
514+
b.iter(|| {
515+
let entry = map.min().unwrap();
516+
black_box(entry);
517+
let mut min = entry.0;
518+
while let Some(entry) = map.get_gt(min) {
519+
black_box(entry);
520+
min = entry.0;
521+
}
522+
});
523+
}
524+
525+
fn bench_iter_with_queries_backward(b: &mut Bencher, size: i32) {
526+
let mut map = BTreeMap::<i32, i32>::new();
527+
let mut rng = thread_rng();
528+
529+
for _ in 0..size {
530+
map.insert(rng.gen(), rng.gen());
531+
}
532+
533+
b.iter(|| {
534+
let entry = map.max().unwrap();
535+
black_box(entry);
536+
let mut max = entry.0;
537+
while let Some(entry) = map.get_lt(max) {
538+
black_box(entry);
539+
max = entry.0;
540+
}
541+
});
542+
}
543+
330544
#[bench]
331-
pub fn iter_20(b: &mut Bencher) {
545+
pub fn iter_20_plain(b: &mut Bencher) {
332546
bench_iter(b, 20);
333547
}
334548

335549
#[bench]
336-
pub fn iter_1000(b: &mut Bencher) {
550+
pub fn iter_1000_plain(b: &mut Bencher) {
337551
bench_iter(b, 1000);
338552
}
339553

340554
#[bench]
341-
pub fn iter_100000(b: &mut Bencher) {
555+
pub fn iter_100000_plain(b: &mut Bencher) {
342556
bench_iter(b, 100000);
343557
}
558+
559+
#[bench]
560+
pub fn iter_20_with_queries_forward(b: &mut Bencher) {
561+
bench_iter_with_queries_forward(b, 20);
562+
}
563+
564+
#[bench]
565+
pub fn iter_1000_with_queries_forward(b: &mut Bencher) {
566+
bench_iter_with_queries_forward(b, 1000);
567+
}
568+
569+
#[bench]
570+
pub fn iter_100000_with_queries_forward(b: &mut Bencher) {
571+
bench_iter_with_queries_forward(b, 100000);
572+
}
573+
574+
#[bench]
575+
pub fn iter_20_with_queries_backward(b: &mut Bencher) {
576+
bench_iter_with_queries_backward(b, 20);
577+
}
578+
579+
#[bench]
580+
pub fn iter_1000_with_queries_backward(b: &mut Bencher) {
581+
bench_iter_with_queries_backward(b, 1000);
582+
}
583+
584+
#[bench]
585+
pub fn iter_100000_with_queries_backward(b: &mut Bencher) {
586+
bench_iter_with_queries_backward(b, 100000);
587+
}
344588
}

src/libcollectionstest/vec_map.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -512,15 +512,17 @@ fn test_extend_ref() {
512512
mod bench {
513513
use std::collections::VecMap;
514514

515+
fn get<'a, V>(map: &'a VecMap<V>, key: &usize) -> Option<&'a V> { map.get(key) }
516+
515517
map_insert_rand_bench!{insert_rand_100, 100, VecMap}
516518
map_insert_rand_bench!{insert_rand_10_000, 10_000, VecMap}
517519

518520
map_insert_seq_bench!{insert_seq_100, 100, VecMap}
519521
map_insert_seq_bench!{insert_seq_10_000, 10_000, VecMap}
520522

521-
map_find_rand_bench!{find_rand_100, 100, VecMap}
522-
map_find_rand_bench!{find_rand_10_000, 10_000, VecMap}
523+
map_find_rand_bench!{find_rand_100, 100, VecMap, get}
524+
map_find_rand_bench!{find_rand_10_000, 10_000, VecMap, get}
523525

524-
map_find_seq_bench!{find_seq_100, 100, VecMap}
525-
map_find_seq_bench!{find_seq_10_000, 10_000, VecMap}
526+
map_find_seq_bench!{find_seq_100, 100, VecMap, get}
527+
map_find_seq_bench!{find_seq_10_000, 10_000, VecMap, get}
526528
}

0 commit comments

Comments
 (0)