|
|
@@ -1,27 +1,43 @@
|
|
|
+#![feature(test)]
|
|
|
+
|
|
|
+macro_rules! DEFINE_NxM_BENCH {
|
|
|
+ ($i:ident, $n:literal, $m:literal) => {
|
|
|
+ mod $i {
|
|
|
+ use super::*;
|
|
|
+
|
|
|
+ #[bench]
|
|
|
+ fn bench_insert_baseline_hashmap(bencher: &mut Bencher) {
|
|
|
+ do_bench_insert_baseline_hashmap(bencher, $n, $m);
|
|
|
+ }
|
|
|
+
|
|
|
+ #[bench]
|
|
|
+ fn bench_insert_bucket_map(bencher: &mut Bencher) {
|
|
|
+ do_bench_insert_bucket_map(bencher, $n, $m);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+}
|
|
|
+
|
|
|
+extern crate test;
|
|
|
use {
|
|
|
- bencher::{benchmark_main, Bencher, TDynBenchFn, TestDesc, TestDescAndFn, TestFn},
|
|
|
rayon::prelude::*,
|
|
|
solana_bucket_map::bucket_map::{BucketMap, BucketMapConfig},
|
|
|
solana_pubkey::Pubkey,
|
|
|
- std::{borrow::Cow, collections::hash_map::HashMap, sync::RwLock, vec},
|
|
|
+ std::{collections::hash_map::HashMap, sync::RwLock},
|
|
|
+ test::Bencher,
|
|
|
};
|
|
|
|
|
|
type IndexValue = u64;
|
|
|
|
|
|
-/// Orphan rules workaround that allows for implementation of `TDynBenchFn`.
|
|
|
-struct Bench<T>(T);
|
|
|
-
|
|
|
-impl<T> TDynBenchFn for Bench<T>
|
|
|
-where
|
|
|
- T: Fn(&mut Bencher) + Send,
|
|
|
-{
|
|
|
- fn run(&self, harness: &mut Bencher) {
|
|
|
- (self.0)(harness)
|
|
|
- }
|
|
|
-}
|
|
|
+DEFINE_NxM_BENCH!(dim_01x02, 1, 2);
|
|
|
+DEFINE_NxM_BENCH!(dim_02x04, 2, 4);
|
|
|
+DEFINE_NxM_BENCH!(dim_04x08, 4, 8);
|
|
|
+DEFINE_NxM_BENCH!(dim_08x16, 8, 16);
|
|
|
+DEFINE_NxM_BENCH!(dim_16x32, 16, 32);
|
|
|
+DEFINE_NxM_BENCH!(dim_32x64, 32, 64);
|
|
|
|
|
|
/// Benchmark insert with Hashmap as baseline for N threads inserting M keys each
|
|
|
-fn do_bench_insert_baseline_hashmap(b: &mut Bencher, n: usize, m: usize) {
|
|
|
+fn do_bench_insert_baseline_hashmap(bencher: &mut Bencher, n: usize, m: usize) {
|
|
|
let index = RwLock::new(HashMap::new());
|
|
|
(0..n).into_par_iter().for_each(|i| {
|
|
|
let key = Pubkey::new_unique();
|
|
|
@@ -30,7 +46,7 @@ fn do_bench_insert_baseline_hashmap(b: &mut Bencher, n: usize, m: usize) {
|
|
|
.unwrap()
|
|
|
.insert(key, vec![(i, IndexValue::default())]);
|
|
|
});
|
|
|
- b.iter(|| {
|
|
|
+ bencher.iter(|| {
|
|
|
(0..n).into_par_iter().for_each(|_| {
|
|
|
for j in 0..m {
|
|
|
let key = Pubkey::new_unique();
|
|
|
@@ -44,13 +60,13 @@ fn do_bench_insert_baseline_hashmap(b: &mut Bencher, n: usize, m: usize) {
|
|
|
}
|
|
|
|
|
|
/// Benchmark insert with BucketMap with N buckets for N threads inserting M keys each
|
|
|
-fn do_bench_insert_bucket_map(b: &mut Bencher, n: usize, m: usize) {
|
|
|
+fn do_bench_insert_bucket_map(bencher: &mut Bencher, n: usize, m: usize) {
|
|
|
let index = BucketMap::new(BucketMapConfig::new(n));
|
|
|
(0..n).into_par_iter().for_each(|i| {
|
|
|
let key = Pubkey::new_unique();
|
|
|
index.update(&key, |_| Some((vec![(i, IndexValue::default())], 0)));
|
|
|
});
|
|
|
- b.iter(|| {
|
|
|
+ bencher.iter(|| {
|
|
|
(0..n).into_par_iter().for_each(|_| {
|
|
|
for j in 0..m {
|
|
|
let key = Pubkey::new_unique();
|
|
|
@@ -59,42 +75,3 @@ fn do_bench_insert_bucket_map(b: &mut Bencher, n: usize, m: usize) {
|
|
|
})
|
|
|
});
|
|
|
}
|
|
|
-
|
|
|
-/// Benchmark cases represented as tuple (N, M), where N represents number of threads and M number of keys
|
|
|
-const BENCH_CASES: &[(usize, usize)] = &[(1, 2), (2, 4), (4, 8), (8, 16), (16, 32), (32, 64)];
|
|
|
-
|
|
|
-/// Logic in this function in big chunk comes from the expanded `bencher::benchmarks_group!` macro
|
|
|
-/// This implementation brings clarity, without the need for separate functions per bench case
|
|
|
-pub fn benches() -> Vec<TestDescAndFn> {
|
|
|
- let mut benches = vec![];
|
|
|
-
|
|
|
- BENCH_CASES.iter().enumerate().for_each(|(i, &(n, m))| {
|
|
|
- let name = format!("{:?}-bench_insert_baseline_hashmap[{:?}, {:?}]", i, n, m);
|
|
|
- benches.push(TestDescAndFn {
|
|
|
- desc: TestDesc {
|
|
|
- name: Cow::from(name),
|
|
|
- ignore: false,
|
|
|
- },
|
|
|
- testfn: TestFn::DynBenchFn(Box::new(Bench(move |b: &mut Bencher| {
|
|
|
- do_bench_insert_baseline_hashmap(b, n, m);
|
|
|
- }))),
|
|
|
- });
|
|
|
- });
|
|
|
-
|
|
|
- BENCH_CASES.iter().enumerate().for_each(|(i, &(n, m))| {
|
|
|
- let name = format!("{:?}-bench_insert_bucket_map[{:?}, {:?}]", i, n, m);
|
|
|
- benches.push(TestDescAndFn {
|
|
|
- desc: TestDesc {
|
|
|
- name: Cow::from(name),
|
|
|
- ignore: false,
|
|
|
- },
|
|
|
- testfn: TestFn::DynBenchFn(Box::new(Bench(move |b: &mut Bencher| {
|
|
|
- do_bench_insert_bucket_map(b, n, m);
|
|
|
- }))),
|
|
|
- });
|
|
|
- });
|
|
|
-
|
|
|
- benches
|
|
|
-}
|
|
|
-
|
|
|
-benchmark_main!(benches);
|