From c9649b50f97ae4daceddab43c45b86e27a092da1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E6=9E=97=E4=BC=9F?= Date: Sun, 29 Oct 2023 20:41:09 +0800 Subject: [PATCH] Add rocksdb bench (#56) --- src/bench/kernel_bench.rs | 133 +++++++++++++++++++--------------- src/bench/util.rs | 76 +++++++++++++++++++ src/kernel/lsm/storage.rs | 2 +- src/kernel/rocksdb_storage.rs | 6 +- src/kernel/sled_storage.rs | 2 +- 5 files changed, 157 insertions(+), 62 deletions(-) create mode 100644 src/bench/util.rs diff --git a/src/bench/kernel_bench.rs b/src/bench/kernel_bench.rs index 957c99f..e8284ce 100644 --- a/src/bench/kernel_bench.rs +++ b/src/bench/kernel_bench.rs @@ -1,3 +1,5 @@ +mod util; + use bytes::Bytes; /// 参考Sled Benchmark /// https://github.com/spacejam/sled/blob/main/benchmarks/criterion/benches/sled.rs @@ -5,44 +7,10 @@ use criterion::{criterion_group, criterion_main, Criterion}; use std::sync::atomic::AtomicU32; use std::sync::atomic::Ordering::Relaxed; +use crate::util::{counter, prepare_data, random, random_bytes}; use kip_db::kernel::lsm::storage::KipStorage; use kip_db::kernel::Storage; -fn counter() -> usize { - use std::sync::atomic::AtomicUsize; - - static C: AtomicUsize = AtomicUsize::new(0); - - C.fetch_add(1, Relaxed) -} - -/// Generates a random number in `0..n`. -fn random(n: u32) -> u32 { - use std::cell::Cell; - use std::num::Wrapping; - - thread_local! { - static RNG: Cell> = Cell::new(Wrapping(1406868647)); - } - - RNG.with(|rng| { - // This is the 32-bit variant of Xorshift. - // - // Source: https://en.wikipedia.org/wiki/Xorshift - let mut x = rng.get(); - x ^= x << 13; - x ^= x >> 17; - x ^= x << 5; - rng.set(x); - - // This is a fast alternative to `x % n`. - // - // Author: Daniel Lemire - // Source: https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/ - ((x.0 as u64).wrapping_mul(n as u64) >> 32) as u32 - }) -} - fn bulk_load(c: &mut Criterion) { let count = AtomicU32::new(0_u32); let bytes = |len| -> Vec { @@ -136,39 +104,64 @@ fn monotonic_crud(c: &mut Criterion) { }); } -fn random_crud(c: &mut Criterion) { - const SIZE: u32 = 65536; +fn random_read(c: &mut Criterion) { + let rt = tokio::runtime::Builder::new_multi_thread() + .worker_threads(8) + .enable_all() + .build() + .unwrap(); + + rt.block_on(async { + let db_path = format!("{}_random_read", T::name()); + let db = T::open(&db_path).await.unwrap(); + + let key_size_range = 1usize..1025usize; + let keys = prepare_data(&db, 100000, key_size_range.clone(), 1usize..1025usize).await; + let keys = keys.into_iter().collect::>(); + let key_count = keys.len(); + println!( + "db size: {:?}, key count: {}", + db.size_of_disk().await, + key_count + ); + + c.bench_function(&format!("Store: {}, random read", T::name()), |b| { + b.iter(|| async { + let index = random(key_count as u32) as usize; + let value = db.get(&keys[index]).await.unwrap(); + assert!(value.is_some()); + }) + }); + + std::fs::remove_dir_all(db_path).unwrap(); + }); +} +fn random_write(c: &mut Criterion) { let rt = tokio::runtime::Builder::new_multi_thread() .worker_threads(8) .enable_all() .build() .unwrap(); + rt.block_on(async { - let db = T::open(format!("{}_random_crud", T::name())).await.unwrap(); + let db_path = format!("{}_random_write", T::name()); + let db = T::open(&db_path).await.unwrap(); - c.bench_function(&format!("Store: {}, random inserts", T::name()), |b| { + c.bench_function(&format!("Store: {}, random write", T::name()), |b| { b.iter(|| async { db.set( - Bytes::from(random(SIZE).to_be_bytes().to_vec()), - Bytes::new(), + Bytes::from(random_bytes(1usize..1025usize)), + Bytes::from(random_bytes(1usize..1025usize)), ) .await .unwrap(); }) }); - c.bench_function(&format!("Store: {}, random gets", T::name()), |b| { - b.iter(|| async { - db.get(&random(SIZE).to_be_bytes()).await.unwrap(); - }) - }); + println!("db size: {:?}", db.size_of_disk().await); - c.bench_function(&format!("Store: {}, random removals", T::name()), |b| { - b.iter(|| async { - db.remove(&random(SIZE).to_be_bytes()).await.unwrap(); - }) - }); + std::fs::remove_dir_all(db_path).unwrap(); }); } @@ -218,17 +211,31 @@ fn kv_monotonic_crud(c: &mut Criterion) { } } -fn kv_random_crud(c: &mut Criterion) { - random_crud::(c); +fn kv_random_read(c: &mut Criterion) { + random_read::(c); #[cfg(feature = "sled")] { use kip_db::kernel::sled_storage::SledStorage; - random_crud::(c); + random_read::(c); } #[cfg(feature = "rocksdb")] { use kip_db::kernel::rocksdb_storage::RocksdbStorage; - random_crud::(c); + random_read::(c); + } +} + +fn kv_random_write(c: &mut Criterion) { + random_write::(c); + #[cfg(feature = "sled")] + { + use kip_db::kernel::sled_storage::SledStorage; + random_write::(c); + } + #[cfg(feature = "rocksdb")] + { + use kip_db::kernel::rocksdb_storage::RocksdbStorage; + random_write::(c); } } @@ -247,10 +254,20 @@ fn kv_empty_opens(c: &mut Criterion) { } criterion_group!( - benches, + name = read_benches; + config = Criterion::default().sample_size(1000); + targets = kv_random_read, +); +criterion_group!( + name = write_benches; + config = Criterion::default().sample_size(100000); + targets = kv_random_write, +); +criterion_group!( + other_benches, kv_bulk_load, kv_monotonic_crud, - kv_random_crud, kv_empty_opens ); -criterion_main!(benches); + +criterion_main!(read_benches, write_benches, other_benches,); diff --git a/src/bench/util.rs b/src/bench/util.rs new file mode 100644 index 0000000..99453f2 --- /dev/null +++ b/src/bench/util.rs @@ -0,0 +1,76 @@ +use bytes::Bytes; +use futures::future::join_all; +use kip_db::kernel::Storage; +use rand::Rng; +use std::collections::HashSet; +use std::ops::Range; +use std::sync::atomic::Ordering::Relaxed; + +pub async fn prepare_data( + db: &T, + data_size: u32, + key_size_range: Range, + value_size_range: Range, +) -> HashSet> { + let mut tasks = Vec::new(); + let mut keys = HashSet::new(); + + // there some dup keys, so final data size is probably less than data_size + for _ in 0..data_size { + let key = random_bytes(key_size_range.clone()); + let value = random_bytes(value_size_range.clone()); + + keys.insert(key.clone()); + tasks.push(db.set(Bytes::from(key), Bytes::from(value))); + } + join_all(tasks).await; + keys +} + +pub fn random_bytes(size_range: Range) -> Vec { + let mut rand = rand::thread_rng(); + + let size = rand.gen_range(size_range); + let mut bytes = Vec::with_capacity(size); + + for _ in 0..size { + bytes.push(rand.gen_range(0..=255)); + } + + bytes +} + +pub fn counter() -> usize { + use std::sync::atomic::AtomicUsize; + + static C: AtomicUsize = AtomicUsize::new(0); + + C.fetch_add(1, Relaxed) +} + +/// Generates a random number in `0..n`. +pub fn random(n: u32) -> u32 { + use std::cell::Cell; + use std::num::Wrapping; + + thread_local! { + static RNG: Cell> = Cell::new(Wrapping(1406868647)); + } + + RNG.with(|rng| { + // This is the 32-bit variant of Xorshift. + // + // Source: https://en.wikipedia.org/wiki/Xorshift + let mut x = rng.get(); + x ^= x << 13; + x ^= x >> 17; + x ^= x << 5; + rng.set(x); + + // This is a fast alternative to `x % n`. + // + // Author: Daniel Lemire + // Source: https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/ + ((x.0 as u64).wrapping_mul(n as u64) >> 32) as u32 + }) +} diff --git a/src/kernel/lsm/storage.rs b/src/kernel/lsm/storage.rs index bf23864..d062652 100644 --- a/src/kernel/lsm/storage.rs +++ b/src/kernel/lsm/storage.rs @@ -103,7 +103,7 @@ impl Storage for KipStorage { where Self: Sized, { - "LSMStore made in Kould" + "KipDB" } #[inline] diff --git a/src/kernel/rocksdb_storage.rs b/src/kernel/rocksdb_storage.rs index 54ae505..34c76a8 100644 --- a/src/kernel/rocksdb_storage.rs +++ b/src/kernel/rocksdb_storage.rs @@ -57,12 +57,14 @@ impl Storage for RocksdbStorage { #[inline] async fn size_of_disk(&self) -> crate::kernel::KernelResult { - unimplemented!("Rocksdb does not support size_of_disk()") + Err(KernelError::NotSupport( + "Rocksdb does not support size_of_disk()", + )) } #[inline] async fn len(&self) -> crate::kernel::KernelResult { - unimplemented!("Rocksdb does not support len()") + Err(KernelError::NotSupport("Rocksdb does not support len()")) } #[inline] diff --git a/src/kernel/sled_storage.rs b/src/kernel/sled_storage.rs index 7f529ab..e3fc79b 100644 --- a/src/kernel/sled_storage.rs +++ b/src/kernel/sled_storage.rs @@ -18,7 +18,7 @@ impl Storage for SledStorage { where Self: Sized, { - "Sled made in spacejam" + "Sled" } #[inline]