diff --git a/Cargo.toml b/Cargo.toml index 129478b217c228bfb6fc72aea92235b6e87c0bfd..b60d1d1ad18006583417c87958aab5397a240e70 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,9 +12,27 @@ path = "src/lib.rs" [dependencies] rand = "0.8.5" tokio = "1.24.1" +jemallocator = "0.5" +jemalloc-sys = {version = "0.5", features = ["stats"]} + +[dev-dependencies] +criterion = "0.3.0" +crc32fast = "1.3.2" +skiplist = "0.4.0" [profile.dev] [profile.release] +[[bench]] +name = "crc_bench" +harness = false + +[[bench]] +name = "skiplist_bench" +harness = false + +[[bench]] +name = "skiplist_memory_useage" +harness = false \ No newline at end of file diff --git a/benches/crc_bench.rs b/benches/crc_bench.rs new file mode 100644 index 0000000000000000000000000000000000000000..e1bdc08bd943ad388c470cfd0da97b29d6f79124 --- /dev/null +++ b/benches/crc_bench.rs @@ -0,0 +1,24 @@ +use criterion::{Criterion, criterion_group, criterion_main}; +use rand::RngCore; +use level_db_rust::util::crc::CRC; + +pub const SRC_DATA: [u8; 512] = [0; 512]; + +pub fn default_crc_bench(c: &mut Criterion) { + let mut rnd = rand::thread_rng(); + c.bench_function("default_crc", |b| { + b.iter(|| { + rnd.fill_bytes(&mut SRC_DATA); + CRC::value(&SRC_DATA); + }); + }); + c.bench_function("crc32fast", |b| { + b.iter(|| { + rnd.fill_bytes(&mut SRC_DATA); + crc32fast::hash(&SRC_DATA); + }); + }); +} + +criterion_group!(benches, default_crc_bench); +criterion_main!(benches); \ No newline at end of file diff --git a/benches/skiplist_bench.rs b/benches/skiplist_bench.rs new file mode 100644 index 0000000000000000000000000000000000000000..bc95bd7077288f26c6b37f00cc7ec094064e60e3 --- /dev/null +++ b/benches/skiplist_bench.rs @@ -0,0 +1,64 @@ +use std::sync::{Arc, Mutex}; + +use criterion::{Criterion, criterion_group, criterion_main}; +use rand::Rng; +use skiplist::OrderedSkipList; + +use level_db_rust::db::skip_list::SkipList; +use level_db_rust::util::Arena; +use level_db_rust::util::arena::ArenaRef; +use level_db_rust::util::comparator::BytewiseComparatorImpl; +use level_db_rust::util::unsafe_slice::TryIntoUnsafeSlice; + + +const BENCH_TIMES: usize = 128; + +pub fn skiplist_bench(c: &mut Criterion) { + // 生成测试样本,保证两次测试都是相同的次数 + let mut rnd = rand::thread_rng(); + let mut every_bench_times = [0; BENCH_TIMES]; + for i in 0..BENCH_TIMES { + every_bench_times[i] = rnd.gen_range(32..20480); + } + + c.bench_function("default_skiplist", |b| { + let mut i = 0; + b.iter(|| { + let cmp = Arc::new(BytewiseComparatorImpl::default()); + let arena = Arc::new(Mutex::new(Arena::default())); + let list = SkipList::create(cmp, arena.clone()); + bench_default_skiplist(list, arena, every_bench_times[i % BENCH_TIMES]); + i += 1; + }); + }); + + c.bench_function("skiplist-0.4.0", |b| { + let mut i = 0; + b.iter(|| { + let list: OrderedSkipList = unsafe { + OrderedSkipList::with_comp(|a: &String, b: &String| { + a.cmp(b) + }) + }; + bench_skiplist_v_0_4_0(list, every_bench_times[i % BENCH_TIMES]); + i += 1; + }); + }); +} + +fn bench_default_skiplist(mut list: SkipList, arena: ArenaRef, record_count: usize) { + for j in 0..record_count { + let value = format!("key_{}", j); + list.insert(value.try_into_unsafe_slice(arena.clone()).unwrap()).unwrap(); + } +} + +fn bench_skiplist_v_0_4_0(mut list: OrderedSkipList, record_count: usize) { + for j in 0..record_count { + let value = format!("key_{}", j); + list.insert(value.clone()); + } +} + +criterion_group!(benches, skiplist_bench); +criterion_main!(benches); \ No newline at end of file diff --git a/benches/skiplist_memory_useage.rs b/benches/skiplist_memory_useage.rs new file mode 100644 index 0000000000000000000000000000000000000000..deaee476e88cf183e8a7d47a9f36ab55c30dfecf --- /dev/null +++ b/benches/skiplist_memory_useage.rs @@ -0,0 +1,55 @@ +use std::ffi::{c_char, c_void}; +use std::ptr::{null, null_mut}; +use std::sync::{Arc, Mutex}; +use skiplist::OrderedSkipList; +use level_db_rust::db::skip_list::SkipList; +use level_db_rust::util::Arena; +use level_db_rust::util::arena::ArenaRef; +use level_db_rust::util::comparator::BytewiseComparatorImpl; +use level_db_rust::util::unsafe_slice::TryIntoUnsafeSlice; + +#[global_allocator] +static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc; + +extern "C" fn write_cb(_: *mut c_void, message: *const c_char) { + print!("{}", String::from_utf8_lossy(unsafe { + std::ffi::CStr::from_ptr(message as *const i8).to_bytes() + })); +} + +fn mem_print() { + unsafe { jemalloc_sys::malloc_stats_print(Some(write_cb), null_mut(), null()) } +} + +fn bench_default_skiplist(mut list: SkipList, arena: ArenaRef, record_count: usize) { + for j in 0..record_count { + let value = format!("key_{}", j); + list.insert(value.try_into_unsafe_slice(arena.clone()).unwrap()).unwrap(); + } + println!("bench_default_skiplist: "); + mem_print(); +} + +fn bench_skiplist_v_0_4_0(mut list: OrderedSkipList, record_count: usize) { + for j in 0..record_count { + let value = format!("key_{}", j); + list.insert(value.clone()); + } + println!("bench_skiplist_v_0_4_0: "); + mem_print(); +} + +fn main() { + let record_count = 100 * 1024; + // let cmp = Arc::new(BytewiseComparatorImpl::default()); + // let arena = Arc::new(Mutex::new(Arena::default())); + // let list = SkipList::create(cmp, arena.clone()); + // bench_default_skiplist(list, arena, record_count); + + let list: OrderedSkipList = unsafe { + OrderedSkipList::with_comp(|a: &String, b: &String| { + a.cmp(b) + }) + }; + bench_skiplist_v_0_4_0(list, record_count); +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index b3fbd97594f29468b6844bbf353f39810fe5a00c..c8b17d305c244fcad61f59965d8b2277006ce518 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,9 +4,9 @@ extern crate core; -mod db; +pub mod db; mod table; -mod util; +pub mod util; mod traits; mod test {