2024-02-12 11:31:35 +00:00
|
|
|
use criterion::measurement::WallTime;
|
|
|
|
use criterion::{criterion_group, criterion_main, BenchmarkGroup, Criterion, Throughput};
|
|
|
|
use radix_trie::{Trie, TrieCommon, TrieKey};
|
|
|
|
use std::collections::{BTreeMap, HashMap};
|
|
|
|
use std::hash::Hash;
|
|
|
|
use std::time::Duration;
|
2024-03-15 11:21:32 +00:00
|
|
|
use surrealdb::sql::{value, Array, Id, Thing};
|
2024-02-12 11:31:35 +00:00
|
|
|
|
|
|
|
// Common use case: VectorSearch
|
|
|
|
fn bench_hash_trie_btree_large_vector(c: &mut Criterion) {
|
|
|
|
const N: usize = 10_000;
|
|
|
|
let mut samples = Vec::with_capacity(N);
|
|
|
|
for i in 0..N {
|
|
|
|
let key = vec![i as u64; 1536];
|
|
|
|
samples.push((key, i));
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut g = new_group(c, "bench_hash_trie_btree_large_vector", N);
|
|
|
|
bench_hash(&mut g, &samples);
|
|
|
|
bench_trie(&mut g, &samples);
|
|
|
|
bench_btree(&mut g, &samples);
|
|
|
|
g.finish();
|
|
|
|
}
|
|
|
|
|
2024-07-20 08:27:14 +00:00
|
|
|
fn bench_hash_trie_btree_ix_key(c: &mut Criterion) {
|
2024-02-12 11:31:35 +00:00
|
|
|
const N: usize = 100_000;
|
|
|
|
let mut samples = Vec::with_capacity(N);
|
|
|
|
for i in 0..N {
|
2024-07-20 08:27:14 +00:00
|
|
|
let mut key = b"/*test\0*test\0*test\0!ixtest".to_vec();
|
|
|
|
key.append(&mut i.to_be_bytes().to_vec());
|
|
|
|
samples.push((key.to_vec(), i));
|
2024-02-12 11:31:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
let mut g = new_group(c, "bench_hash_trie_btree_ix_key", N);
|
|
|
|
bench_hash(&mut g, &samples);
|
|
|
|
bench_trie(&mut g, &samples);
|
|
|
|
bench_btree(&mut g, &samples);
|
|
|
|
g.finish();
|
2024-07-20 08:27:14 +00:00
|
|
|
}
|
2024-02-12 11:31:35 +00:00
|
|
|
|
|
|
|
fn bench_hash_trie_btree_small_string(c: &mut Criterion) {
|
|
|
|
const N: usize = 100_000;
|
|
|
|
let mut samples = Vec::with_capacity(N);
|
|
|
|
for i in 0..N {
|
|
|
|
let key = format!("test{i}");
|
|
|
|
samples.push((key, i));
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut g = new_group(c, "bench_hash_trie_btree_string", N);
|
|
|
|
bench_hash(&mut g, &samples);
|
|
|
|
bench_trie(&mut g, &samples);
|
|
|
|
bench_btree(&mut g, &samples);
|
|
|
|
g.finish();
|
|
|
|
}
|
|
|
|
|
|
|
|
fn bench_hash_trie_btree_value(c: &mut Criterion) {
|
|
|
|
const N: usize = 100_000;
|
|
|
|
let mut samples = Vec::with_capacity(N);
|
|
|
|
for i in 0..N {
|
|
|
|
let key = value(&format!("{{ test: {{ something: [1, 'two', null, test:{i}, {{ trueee: false, noneee: nulll }}] }} }}")).unwrap();
|
|
|
|
samples.push((key, i));
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut g = new_group(c, "bench_hash_trie_btree_value", N);
|
|
|
|
bench_hash(&mut g, &samples);
|
|
|
|
bench_btree(&mut g, &samples);
|
|
|
|
g.finish();
|
|
|
|
}
|
|
|
|
|
|
|
|
fn bench_hash_trie_btree_thing(c: &mut Criterion) {
|
|
|
|
const N: usize = 50_000;
|
|
|
|
let mut samples = Vec::with_capacity(N);
|
|
|
|
for i in 0..N {
|
2024-08-20 11:42:06 +00:00
|
|
|
let key = Thing::from(("test", Id::from(Array::from(vec![i as i32; 5]))));
|
2024-02-12 11:31:35 +00:00
|
|
|
samples.push((key, i));
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut g = new_group(c, "bench_hash_trie_btree_thing", N);
|
|
|
|
bench_hash(&mut g, &samples);
|
|
|
|
bench_btree(&mut g, &samples);
|
|
|
|
g.finish();
|
|
|
|
}
|
|
|
|
|
|
|
|
fn new_group<'a>(c: &'a mut Criterion, group: &str, n: usize) -> BenchmarkGroup<'a, WallTime> {
|
|
|
|
let mut group = c.benchmark_group(group);
|
|
|
|
group.throughput(Throughput::Elements(n as u64));
|
|
|
|
group.sample_size(10);
|
|
|
|
group.measurement_time(Duration::from_secs(10));
|
|
|
|
group
|
|
|
|
}
|
|
|
|
|
|
|
|
fn bench_hash<K: Hash + Eq + Clone, V: Clone>(
|
|
|
|
group: &mut BenchmarkGroup<WallTime>,
|
|
|
|
samples: &[(K, V)],
|
|
|
|
) {
|
|
|
|
group.bench_function("hash_insert", |b| {
|
2024-03-08 10:58:07 +00:00
|
|
|
b.iter(|| bench_hash_insert(samples));
|
2024-02-12 11:31:35 +00:00
|
|
|
});
|
|
|
|
group.bench_function("hash_get", |b| {
|
2024-03-08 10:58:07 +00:00
|
|
|
let map = build_hash(samples);
|
|
|
|
b.iter(|| bench_hash_get(samples, &map));
|
2024-02-12 11:31:35 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
fn bench_trie<K: TrieKey + Clone, V: Clone>(
|
|
|
|
group: &mut BenchmarkGroup<WallTime>,
|
|
|
|
samples: &[(K, V)],
|
|
|
|
) {
|
|
|
|
group.bench_function("trie_insert", |b| {
|
2024-03-08 10:58:07 +00:00
|
|
|
b.iter(|| bench_trie_insert(samples));
|
2024-02-12 11:31:35 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
group.bench_function("trie_get", |b| {
|
2024-03-08 10:58:07 +00:00
|
|
|
let map = build_trie(samples);
|
|
|
|
b.iter(|| bench_trie_get(samples, &map));
|
2024-02-12 11:31:35 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
fn bench_btree<K: Eq + Ord + Clone, V: Clone>(
|
|
|
|
group: &mut BenchmarkGroup<WallTime>,
|
|
|
|
samples: &[(K, V)],
|
|
|
|
) {
|
|
|
|
group.bench_function("btree_insert", |b| {
|
2024-03-08 10:58:07 +00:00
|
|
|
b.iter(|| bench_btree_insert(samples));
|
2024-02-12 11:31:35 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
group.bench_function("btree_get", |b| {
|
2024-03-08 10:58:07 +00:00
|
|
|
let map = build_btree(samples);
|
|
|
|
b.iter(|| bench_btree_get(samples, &map));
|
2024-02-12 11:31:35 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
fn build_hash<K: Hash + Eq + Clone, V: Clone>(samples: &[(K, V)]) -> HashMap<K, V> {
|
|
|
|
let mut map = HashMap::default();
|
|
|
|
for (key, val) in samples {
|
|
|
|
map.insert(key.clone(), val.clone());
|
|
|
|
}
|
|
|
|
map
|
|
|
|
}
|
|
|
|
fn bench_hash_insert<K: Hash + Eq + Clone, V: Clone>(samples: &[(K, V)]) {
|
|
|
|
let map = build_hash(samples);
|
|
|
|
assert_eq!(map.len(), samples.len());
|
|
|
|
}
|
|
|
|
|
|
|
|
fn bench_hash_get<K: Hash + Eq, V>(samples: &[(K, V)], map: &HashMap<K, V>) {
|
|
|
|
for (key, _) in samples {
|
|
|
|
assert!(map.get(key).is_some());
|
|
|
|
}
|
|
|
|
assert_eq!(map.len(), samples.len());
|
|
|
|
}
|
|
|
|
|
|
|
|
fn build_trie<K: TrieKey + Clone, V: Clone>(samples: &[(K, V)]) -> Trie<K, V> {
|
|
|
|
let mut map = Trie::default();
|
|
|
|
for (key, val) in samples {
|
|
|
|
map.insert(key.clone(), val.clone());
|
|
|
|
}
|
|
|
|
map
|
|
|
|
}
|
|
|
|
|
|
|
|
fn bench_trie_insert<K: TrieKey + Clone, V: Clone>(samples: &[(K, V)]) {
|
|
|
|
let map = build_trie(samples);
|
|
|
|
assert_eq!(map.len(), samples.len());
|
|
|
|
}
|
|
|
|
|
|
|
|
fn bench_trie_get<K: TrieKey, V>(samples: &[(K, V)], map: &Trie<K, V>) {
|
|
|
|
for (key, _) in samples {
|
|
|
|
assert!(map.get(key).is_some());
|
|
|
|
}
|
|
|
|
assert_eq!(map.len(), samples.len());
|
|
|
|
}
|
|
|
|
|
|
|
|
fn build_btree<K: Ord + Clone, V: Clone>(samples: &[(K, V)]) -> BTreeMap<K, V> {
|
|
|
|
let mut map = BTreeMap::default();
|
|
|
|
for (key, val) in samples {
|
|
|
|
map.insert(key.clone(), val.clone());
|
|
|
|
}
|
|
|
|
map
|
|
|
|
}
|
|
|
|
|
|
|
|
fn bench_btree_insert<K: Ord + Clone, V: Clone>(samples: &[(K, V)]) {
|
|
|
|
let map = build_btree(samples);
|
|
|
|
assert_eq!(map.len(), samples.len());
|
|
|
|
}
|
|
|
|
|
|
|
|
fn bench_btree_get<K: Ord, V>(samples: &[(K, V)], map: &BTreeMap<K, V>) {
|
|
|
|
for (key, _) in samples {
|
|
|
|
assert!(map.get(key).is_some());
|
|
|
|
}
|
|
|
|
assert_eq!(map.len(), samples.len());
|
|
|
|
}
|
|
|
|
|
|
|
|
criterion_group!(
|
|
|
|
benches,
|
|
|
|
bench_hash_trie_btree_large_vector,
|
2024-07-20 08:27:14 +00:00
|
|
|
bench_hash_trie_btree_ix_key,
|
2024-02-12 11:31:35 +00:00
|
|
|
bench_hash_trie_btree_small_string,
|
|
|
|
bench_hash_trie_btree_thing,
|
|
|
|
bench_hash_trie_btree_value
|
|
|
|
);
|
|
|
|
criterion_main!(benches);
|