فهرست منبع

bench: compare crossbeam SkipMap with Mutex<HashMap<...>>

darkfi 2 سال پیش
والد
کامیت
2dc0b414bd
3فایلهای تغییر یافته به همراه132 افزوده شده و 0 حذف شده
  1. 11 0
      Cargo.lock
  2. 6 0
      Cargo.toml
  3. 115 0
      bench/crossbeam.rs

+ 11 - 0
Cargo.lock

@@ -1734,6 +1734,16 @@ dependencies = [
  "crossbeam-utils",
 ]
 
+[[package]]
+name = "crossbeam-skiplist"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df29de440c58ca2cc6e587ec3d22347551a32435fbde9d2bff64e78a9ffa151b"
+dependencies = [
+ "crossbeam-epoch",
+ "crossbeam-utils",
+]
+
 [[package]]
 name = "crossbeam-utils"
 version = "0.8.20"
@@ -1981,6 +1991,7 @@ dependencies = [
  "chrono",
  "clap 4.5.4",
  "criterion",
+ "crossbeam-skiplist",
  "crypto_api_chachapoly",
  "darkfi-derive",
  "darkfi-sdk",

+ 6 - 0
Cargo.toml

@@ -136,6 +136,8 @@ easy-parallel = "3.3.1"
 prettytable-rs = "0.10.0"
 # Used for benchmarks
 criterion = { version = "0.5.1", features = ["html_reports"] }
+crossbeam-skiplist = "0.1.3"
+rand = "0.8.5"
 
 # -----BEGIN LIBRARY FEATURES-----
 [features]
@@ -345,6 +347,10 @@ path = "bench/zk_from_json.rs"
 name = "sled"
 harness = false
 path = "bench/sled.rs"
+[[bench]]
+name = "crossbeam"
+harness = false
+path = "bench/crossbeam.rs"
 
 # Top-level lints. Enabled optionally on a crate-level in their respective Cargo.toml files.
 [workspace.lints.clippy]

+ 115 - 0
bench/crossbeam.rs

@@ -0,0 +1,115 @@
+/* This file is part of DarkFi (https://dark.fi)
+ *
+ * Copyright (C) 2020-2024 Dyne.org foundation
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
+use easy_parallel::Parallel;
+use std::{collections::HashMap, sync::{Arc, Mutex, atomic::{AtomicBool, Ordering}}};
+use rand::{rngs::OsRng, Rng};
+use crossbeam_skiplist::SkipMap;
+
+fn crossbeam(c: &mut Criterion) {
+    let mut group = c.benchmark_group("crossbeam");
+
+    for k in 1..10 {
+        let stopped = Arc::new(AtomicBool::new(false));
+        let map = Arc::new(SkipMap::new());
+
+        let stopped2 = stopped.clone();
+        let map2 = map.clone();
+
+        // Start n threads all doing continuous inserts until we tell them to stop
+        let parallel_inserts = std::thread::spawn(move || {
+            Parallel::new()
+                .each(0..k, |_| {
+                    let stopped = stopped2.clone();
+                    let map = map2.clone();
+
+                    while !stopped.load(Ordering::Relaxed) {
+                        let key: usize = OsRng.gen();
+                        let val: usize = OsRng.gen();
+                        map.insert(key, val);
+                    }
+                })
+                .run();
+        });
+
+        group.bench_with_input(BenchmarkId::from_parameter(k), &k, |b, &_| {
+            b.iter(|| {
+                // Do 10k inserts
+                for _ in 0..10_000 {
+                    let key: usize = OsRng.gen();
+                    let val: usize = OsRng.gen();
+                    map.insert(key, val);
+                }
+            })
+        });
+
+        stopped.store(true, Ordering::Relaxed);
+        parallel_inserts.join().unwrap();
+    }
+
+    group.finish();
+
+    // Now try normal Mutex hashmap
+    // This is not an async Mutex, but async Mutexes are always slower than sync ones anyway
+    // since they just implement an async interface on top of sync Mutexes.
+    let mut group = c.benchmark_group("mutex_hashmap");
+
+    for k in 1..10 {
+        let stopped = Arc::new(AtomicBool::new(false));
+        let map = Arc::new(Mutex::new(HashMap::new()));
+
+        let stopped2 = stopped.clone();
+        let map2 = map.clone();
+
+        // Start n threads all doing continuous inserts until we tell them to stop
+        let parallel_inserts = std::thread::spawn(move || {
+            Parallel::new()
+                .each(0..k, |_| {
+                    let stopped = stopped2.clone();
+                    let map = map2.clone();
+
+                    while !stopped.load(Ordering::Relaxed) {
+                        let key: usize = OsRng.gen();
+                        let val: usize = OsRng.gen();
+                        map.lock().unwrap().insert(key, val);
+                    }
+                })
+                .run();
+        });
+
+        group.bench_with_input(BenchmarkId::from_parameter(k), &k, |b, &_| {
+            b.iter(|| {
+                // Do 10k inserts
+                for _ in 0..10_000 {
+                    let key: usize = OsRng.gen();
+                    let val: usize = OsRng.gen();
+                    map.lock().unwrap().insert(key, val);
+                }
+            })
+        });
+
+        stopped.store(true, Ordering::Relaxed);
+        parallel_inserts.join().unwrap();
+    }
+
+    group.finish();
+}
+
+criterion_group!(bench, crossbeam);
+criterion_main!(bench);