From e08697bf2323a329d4955515490326d6a2ecb4c6 Mon Sep 17 00:00:00 2001 From: WetABQ Date: Thu, 24 Oct 2024 04:18:03 -0500 Subject: [PATCH 1/4] bench: add btree and dash benchmark --- Cargo.toml | 1 + bench/basic.rs | 144 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 144 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index cb1ad74..7d52bd1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,7 @@ shumai = "0.2.15" serde = "1.0.210" serde_json = "1.0.128" flurry = "0.5.1" +dashmap = "6.1.0" mimalloc = { version = "0.1.43", default-features = false } selfsimilar = "0.1.0" shuttle = "0.8.0" diff --git a/bench/basic.rs b/bench/basic.rs index e764702..0717d35 100644 --- a/bench/basic.rs +++ b/bench/basic.rs @@ -2,7 +2,7 @@ use congee::Art; use rand::{thread_rng, Rng}; use serde::{Deserialize, Serialize}; use shumai::{config, ShumaiBench}; -use std::{cell::UnsafeCell, fmt::Display}; +use std::{collections::BTreeMap, cell::UnsafeCell, fmt::Display}; use mimalloc::MiMalloc; @@ -26,6 +26,8 @@ impl Display for Workload { #[derive(Serialize, Clone, Copy, Debug, Deserialize)] pub enum IndexType { SingleHashMap, + BTree, + Dash, Flurry, ART, } @@ -75,6 +77,80 @@ trait DBIndex: Send + Sync { ) -> usize; } +struct BTreeMapWrapper { + map: UnsafeCell>, // only allow single thread access +} + +impl BTreeMapWrapper { + fn new() -> Self { + Self { + map: UnsafeCell::new(BTreeMap::new()), + } + } +} + +unsafe impl Send for BTreeMapWrapper {} +unsafe impl Sync for BTreeMapWrapper {} + +impl DBIndex for BTreeMapWrapper { + type Guard<'a> = (); + + fn pin(&self) -> Self::Guard<'_> { + () + } + + fn insert<'a>(&'a self, key: usize, v: usize, _: &Self::Guard<'a>) { + unsafe { + (*self.map.get()).insert(key, v); + } + } + + fn get<'a>(&'a self, key: &usize, _: &Self::Guard<'a>) -> Option { + unsafe { + (*self.map.get()).get(key).cloned() + } + } + + fn update<'a>( + &'a self, + key: &usize, + new: usize, + _: &Self::Guard<'a>, + ) -> Option<(usize, Option)> { + unsafe { + (*self.map.get()) + .entry(*key) + .and_modify(|v| *v = new) + .or_insert(new); + } + Some((*key, Some(*key))) + } + + fn scan<'a>( + &'a self, + low_key: &usize, + high_key: &usize, + results: &mut [(usize, usize)], + _: &Self::Guard<'a>, + ) -> usize { + unsafe { + let map = &*self.map.get(); + let range = map.range(low_key..=high_key); + let mut count = 0; + for (k, v) in range { + if count >= results.len() { + break; + } + results[count] = (*k, *v); + count += 1; + } + count + } + } + + +} + impl DBIndex for Art { type Guard<'a> = crossbeam_epoch::Guard; @@ -211,6 +287,56 @@ impl DBIndex for flurry::HashMap { } } +impl DBIndex for dashmap::DashMap { + type Guard<'a> = (); + + fn pin(&self) -> Self::Guard<'_> { + () + } + + fn insert<'a>(&'a self, key: usize, v: usize, _: &Self::Guard<'a>) { + self.insert(key, v); + } + + fn get<'a>(&'a self, key: &usize, _: &Self::Guard<'a>) -> Option { + self.get(key).map(|v| *v) + } + + fn update<'a>( + &'a self, + key: &usize, + new: usize, + _: &Self::Guard<'a>, + ) -> Option<(usize, Option)> { + self.alter(key, |_, _| new); + Some((*key, Some(*key))) + } + + fn scan<'a>( + &'a self, + low_key: &usize, + high_key: &usize, + results: &mut [(usize, usize)], + _: &Self::Guard<'a>, + ) -> usize { + let mut count = 0; + for entry in self.iter() { + let key = *entry.key(); + if key >= *low_key && key < *high_key { + if count < results.len() { + results[count] = (key, *entry.value()); + count += 1; + } else { + break; + } + } + } + count + } + + +} + impl ShumaiBench for TestBench { type Config = Basic; type Result = usize; @@ -280,6 +406,22 @@ fn main() { for c in config.iter() { match c.index_type { + IndexType::BTree => { + let mut test_bench = TestBench { + index: BTreeMapWrapper::new(), + initial_cnt: 50_000_000, + }; + let result = shumai::run(&mut test_bench, c, repeat); + result.write_json().unwrap(); + } + IndexType::Dash => { + let mut test_bench = TestBench { + index: dashmap::DashMap::new(), + initial_cnt: 50_000_000, + }; + let result = shumai::run(&mut test_bench, c, repeat); + result.write_json().unwrap(); + } IndexType::Flurry => { let mut test_bench = TestBench { index: flurry::HashMap::new(), From 4ba379a9d40f0ec110327c513a802a154c8a0b2b Mon Sep 17 00:00:00 2001 From: WetABQ Date: Thu, 24 Oct 2024 04:29:48 -0500 Subject: [PATCH 2/4] bench: add dash, btree into benchmark config --- bench/benchmark.toml | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/bench/benchmark.toml b/bench/benchmark.toml index 4e529ee..ab9dbac 100644 --- a/bench/benchmark.toml +++ b/bench/benchmark.toml @@ -3,7 +3,7 @@ name = "basic" threads = [1, 2, 4, 8, 32] time = 3 workload = ["ReadOnly", "InsertOnly", "UpdateOnly", "ScanOnly"] -index_type = ["Flurry", "ART"] +index_type = ["Flurry", "ART", "Dash", "BTree"] [[Basic]] name = "single-thread" @@ -12,6 +12,19 @@ time = 3 workload = ["ReadOnly"] index_type = ["ART", "SingleHashMap"] +[[Basic]] +name = "dash" +threads = [1, 2, 4, 8, 32] +time = 3 +workload = ["ReadOnly", "InsertOnly", "UpdateOnly", "ScanOnly"] +index_type = ["Dash"] + +[[Basic]] +name = "btree" +threads = [1, 2, 4, 8, 32] +time = 3 +workload = ["ReadOnly", "InsertOnly", "UpdateOnly", "ScanOnly"] +index_type = ["BTree"] [[Scan]] name = "scan" From b625ed72522a1ac77f082ee040a2442e0658ef98 Mon Sep 17 00:00:00 2001 From: WetABQ Date: Fri, 25 Oct 2024 01:46:55 -0500 Subject: [PATCH 3/4] bench: fix --- bench/basic.rs | 14 +------------- bench/benchmark.toml | 10 +++++----- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/bench/basic.rs b/bench/basic.rs index 0717d35..f1b96c1 100644 --- a/bench/basic.rs +++ b/bench/basic.rs @@ -319,19 +319,7 @@ impl DBIndex for dashmap::DashMap { results: &mut [(usize, usize)], _: &Self::Guard<'a>, ) -> usize { - let mut count = 0; - for entry in self.iter() { - let key = *entry.key(); - if key >= *low_key && key < *high_key { - if count < results.len() { - results[count] = (key, *entry.value()); - count += 1; - } else { - break; - } - } - } - count + unimplemented!("DashMap can't scan") } diff --git a/bench/benchmark.toml b/bench/benchmark.toml index ab9dbac..37fdd73 100644 --- a/bench/benchmark.toml +++ b/bench/benchmark.toml @@ -10,20 +10,20 @@ name = "single-thread" threads = [1] time = 3 workload = ["ReadOnly"] -index_type = ["ART", "SingleHashMap"] +index_type = ["ART", "SingleHashMap", "BTree", "Dash"] -[[Basic]] +[[Basic]] name = "dash" threads = [1, 2, 4, 8, 32] time = 3 -workload = ["ReadOnly", "InsertOnly", "UpdateOnly", "ScanOnly"] +workload = ["ReadOnly", "InsertOnly", "UpdateOnly"] index_type = ["Dash"] [[Basic]] name = "btree" -threads = [1, 2, 4, 8, 32] +threads = [1] time = 3 -workload = ["ReadOnly", "InsertOnly", "UpdateOnly", "ScanOnly"] +workload = ["ReadOnly", "InsertOnly", "UpdateOnly"] index_type = ["BTree"] [[Scan]] From d1830e9a19bdb62a6c603399cbd5cc33a83cfae9 Mon Sep 17 00:00:00 2001 From: WetABQ Date: Wed, 30 Oct 2024 09:37:15 -0500 Subject: [PATCH 4/4] format: fix format and add pre-commit script --- .git-hooks/pre-commit | 11 +++++++++++ bench/basic.rs | 26 ++++++++++---------------- 2 files changed, 21 insertions(+), 16 deletions(-) create mode 100755 .git-hooks/pre-commit diff --git a/.git-hooks/pre-commit b/.git-hooks/pre-commit new file mode 100755 index 0000000..ea9c038 --- /dev/null +++ b/.git-hooks/pre-commit @@ -0,0 +1,11 @@ +#!/bin/sh + +# Run cargo fmt and check if there are any changes +cargo fmt --all -- --check +if [ $? -ne 0 ]; then + echo "❌ Formatting check failed. Please run 'cargo fmt' to format your code." + exit 1 +fi + +echo "✅ Formatting check passed." +exit 0 diff --git a/bench/basic.rs b/bench/basic.rs index f1b96c1..846a643 100644 --- a/bench/basic.rs +++ b/bench/basic.rs @@ -2,7 +2,7 @@ use congee::Art; use rand::{thread_rng, Rng}; use serde::{Deserialize, Serialize}; use shumai::{config, ShumaiBench}; -use std::{collections::BTreeMap, cell::UnsafeCell, fmt::Display}; +use std::{cell::UnsafeCell, collections::BTreeMap, fmt::Display}; use mimalloc::MiMalloc; @@ -98,19 +98,17 @@ impl DBIndex for BTreeMapWrapper { fn pin(&self) -> Self::Guard<'_> { () } - + fn insert<'a>(&'a self, key: usize, v: usize, _: &Self::Guard<'a>) { unsafe { (*self.map.get()).insert(key, v); } } - + fn get<'a>(&'a self, key: &usize, _: &Self::Guard<'a>) -> Option { - unsafe { - (*self.map.get()).get(key).cloned() - } + unsafe { (*self.map.get()).get(key).cloned() } } - + fn update<'a>( &'a self, key: &usize, @@ -125,7 +123,7 @@ impl DBIndex for BTreeMapWrapper { } Some((*key, Some(*key))) } - + fn scan<'a>( &'a self, low_key: &usize, @@ -147,8 +145,6 @@ impl DBIndex for BTreeMapWrapper { count } } - - } impl DBIndex for Art { @@ -293,15 +289,15 @@ impl DBIndex for dashmap::DashMap { fn pin(&self) -> Self::Guard<'_> { () } - + fn insert<'a>(&'a self, key: usize, v: usize, _: &Self::Guard<'a>) { self.insert(key, v); } - + fn get<'a>(&'a self, key: &usize, _: &Self::Guard<'a>) -> Option { self.get(key).map(|v| *v) } - + fn update<'a>( &'a self, key: &usize, @@ -311,7 +307,7 @@ impl DBIndex for dashmap::DashMap { self.alter(key, |_, _| new); Some((*key, Some(*key))) } - + fn scan<'a>( &'a self, low_key: &usize, @@ -321,8 +317,6 @@ impl DBIndex for dashmap::DashMap { ) -> usize { unimplemented!("DashMap can't scan") } - - } impl ShumaiBench for TestBench {