Skip to content

Commit

Permalink
Merge pull request #90 from xfbs/benchmark
Browse files Browse the repository at this point in the history
Adds benchmarks for insertion/operations/lookup
  • Loading branch information
jeffparsons authored Feb 7, 2024
2 parents ba9a3e2 + 9d9d66e commit 2cc8ce9
Show file tree
Hide file tree
Showing 3 changed files with 167 additions and 41 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,5 @@ nightly = []
const_fn = []

[[bench]]
name = "kitchen_sink"
name = "benches"
harness = false
166 changes: 166 additions & 0 deletions benches/benches.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
use criterion::{black_box, criterion_group, criterion_main, Criterion, Throughput};
use proptest::{prelude::*, strategy::ValueTree, test_runner::TestRunner};
use rangemap::*;
use std::{any::type_name, fmt::Debug, ops::*};
use test_strategy::Arbitrary;

type Key = i64;
type Value = i64;

const COUNT: usize = 100000;
const OPERATIONS: usize = 100000;
const LOOKUPS: usize = 1000000;

#[derive(Debug, Clone, Arbitrary)]
enum Operation<K, V> {
Insert(K, V),
Delete(K),
}

fn range_inclusive_map<K: Ord + StepLite + Debug + Clone, V: Eq + Clone + Debug>(
values: impl Strategy<Value = (RangeInclusive<K>, V)>,
size: usize,
) -> impl Strategy<Value = RangeInclusiveMap<K, V>> {
prop::collection::vec(values, size)
.prop_map(|ranges| ranges.into_iter().collect::<RangeInclusiveMap<K, V>>())
}

fn range_map<K: Ord + StepLite + Debug + Clone, V: Eq + Clone + Debug>(
values: impl Strategy<Value = (Range<K>, V)>,
size: usize,
) -> impl Strategy<Value = RangeMap<K, V>> {
prop::collection::vec(values, size)
.prop_map(|ranges| ranges.into_iter().collect::<RangeMap<K, V>>())
}

fn criterion_benchmark(c: &mut Criterion) {
let mut runner = TestRunner::deterministic();

let mut group = c.benchmark_group(&format!(
"RangeMap<{}, {}>",
type_name::<Key>(),
type_name::<Value>()
));

group.throughput(Throughput::Elements(COUNT as u64));
group.bench_function("insert", |b| {
let entries = prop::collection::vec(any::<(Range<Key>, Value)>(), COUNT)
.new_tree(&mut runner)
.unwrap()
.current();
b.iter_with_large_drop(|| {
let mut map = RangeMap::new();
for (range, value) in entries.clone().into_iter() {
map.insert(range, value);
}
map
})
});

group.throughput(Throughput::Elements(OPERATIONS as u64));
group.bench_function("operations", |b| {
let map = range_map(any::<(Range<Key>, Value)>(), COUNT)
.new_tree(&mut runner)
.unwrap()
.current();
let operations = prop::collection::vec(any::<Operation<Range<Key>, Value>>(), OPERATIONS)
.new_tree(&mut runner)
.unwrap()
.current();
b.iter_with_large_drop(|| {
let mut map = map.clone();
for operation in operations.clone().into_iter() {
match operation {
Operation::Insert(key, value) => map.insert(key, value),
Operation::Delete(key) => map.remove(key),
}
}
map
})
});

group.throughput(Throughput::Elements(LOOKUPS as u64));
group.bench_function("lookups", |b| {
let map = range_map(any::<(Range<Key>, Value)>(), COUNT)
.new_tree(&mut runner)
.unwrap()
.current();
let lookups = prop::collection::vec(any::<Key>(), LOOKUPS)
.new_tree(&mut runner)
.unwrap()
.current();
b.iter(|| {
for lookup in lookups.iter() {
black_box(map.get(lookup));
}
})
});

group.finish();

let mut group = c.benchmark_group(&format!(
"RangeInclusiveMap<{}, {}>",
type_name::<Key>(),
type_name::<Value>()
));

group.throughput(Throughput::Elements(COUNT as u64));
group.bench_function("insert", |b| {
let entries = prop::collection::vec(any::<(RangeInclusive<Key>, Value)>(), COUNT)
.new_tree(&mut runner)
.unwrap()
.current();
b.iter_with_large_drop(|| {
let mut map = RangeInclusiveMap::new();
for (range, value) in entries.clone().into_iter() {
map.insert(range, value);
}
map
})
});

group.throughput(Throughput::Elements(OPERATIONS as u64));
group.bench_function("operations", |b| {
let map = range_inclusive_map(any::<(RangeInclusive<Key>, Value)>(), COUNT)
.new_tree(&mut runner)
.unwrap()
.current();
let operations =
prop::collection::vec(any::<Operation<RangeInclusive<Key>, Value>>(), OPERATIONS)
.new_tree(&mut runner)
.unwrap()
.current();
b.iter_with_large_drop(|| {
let mut map = map.clone();
for operation in operations.clone().into_iter() {
match operation {
Operation::Insert(key, value) => map.insert(key, value),
Operation::Delete(key) => map.remove(key),
}
}
map
})
});

group.throughput(Throughput::Elements(LOOKUPS as u64));
group.bench_function("lookups", |b| {
let map = range_inclusive_map(any::<(RangeInclusive<Key>, Value)>(), COUNT)
.new_tree(&mut runner)
.unwrap()
.current();
let lookups = prop::collection::vec(any::<Key>(), LOOKUPS)
.new_tree(&mut runner)
.unwrap()
.current();
b.iter(|| {
for lookup in lookups.iter() {
black_box(map.get(lookup));
}
})
});

group.finish();
}

criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);
40 changes: 0 additions & 40 deletions benches/kitchen_sink.rs

This file was deleted.

0 comments on commit 2cc8ce9

Please sign in to comment.