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/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..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::{cell::UnsafeCell, fmt::Display}; +use std::{cell::UnsafeCell, collections::BTreeMap, 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,76 @@ 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 +283,42 @@ 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 { + unimplemented!("DashMap can't scan") + } +} + impl ShumaiBench for TestBench { type Config = Basic; type Result = usize; @@ -280,6 +388,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(), diff --git a/bench/benchmark.toml b/bench/benchmark.toml index 4e529ee..37fdd73 100644 --- a/bench/benchmark.toml +++ b/bench/benchmark.toml @@ -3,15 +3,28 @@ 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" threads = [1] time = 3 workload = ["ReadOnly"] -index_type = ["ART", "SingleHashMap"] +index_type = ["ART", "SingleHashMap", "BTree", "Dash"] +[[Basic]] +name = "dash" +threads = [1, 2, 4, 8, 32] +time = 3 +workload = ["ReadOnly", "InsertOnly", "UpdateOnly"] +index_type = ["Dash"] + +[[Basic]] +name = "btree" +threads = [1] +time = 3 +workload = ["ReadOnly", "InsertOnly", "UpdateOnly"] +index_type = ["BTree"] [[Scan]] name = "scan"