use chainfire_storage::kv_store::KvStore; use chainfire_storage::RocksStore; use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; use std::time::Duration; use tempfile::TempDir; const VALUE_SIZE: usize = 1024; // 1KB const NUM_KEYS_THROUGHPUT: usize = 10_000; // 10K for throughput tests fn bench_write_throughput(c: &mut Criterion) { let temp_dir = TempDir::new().unwrap(); let rocks_store = RocksStore::new(temp_dir.path()).unwrap(); let store = KvStore::new(rocks_store).unwrap(); let value = vec![b'x'; VALUE_SIZE]; let mut group = c.benchmark_group("write_throughput"); group.throughput(Throughput::Elements(NUM_KEYS_THROUGHPUT as u64)); group.sample_size(10); group.measurement_time(Duration::from_secs(20)); group.bench_function(BenchmarkId::from_parameter(NUM_KEYS_THROUGHPUT), |b| { b.iter(|| { for i in 0..NUM_KEYS_THROUGHPUT { let key = format!("bench_key_{:08}", i).into_bytes(); store.put(black_box(key), black_box(value.clone()), None).unwrap(); } }); }); group.finish(); } fn bench_read_throughput(c: &mut Criterion) { let temp_dir = TempDir::new().unwrap(); let rocks_store = RocksStore::new(temp_dir.path()).unwrap(); let store = KvStore::new(rocks_store).unwrap(); let value = vec![b'x'; VALUE_SIZE]; // Pre-populate keys for i in 0..NUM_KEYS_THROUGHPUT { let key = format!("bench_key_{:08}", i).into_bytes(); store.put(key, value.clone(), None).unwrap(); } let mut group = c.benchmark_group("read_throughput"); group.throughput(Throughput::Elements(NUM_KEYS_THROUGHPUT as u64)); group.sample_size(10); group.measurement_time(Duration::from_secs(20)); group.bench_function(BenchmarkId::from_parameter(NUM_KEYS_THROUGHPUT), |b| { b.iter(|| { for i in 0..NUM_KEYS_THROUGHPUT { let key = format!("bench_key_{:08}", i).into_bytes(); let _ = store.get(black_box(&key)).unwrap(); } }); }); group.finish(); } fn bench_write_latency(c: &mut Criterion) { let temp_dir = TempDir::new().unwrap(); let rocks_store = RocksStore::new(temp_dir.path()).unwrap(); let store = KvStore::new(rocks_store).unwrap(); let value = vec![b'x'; VALUE_SIZE]; let mut group = c.benchmark_group("write_latency"); group.sample_size(1000); // Larger sample for better p99/p999 estimates group.measurement_time(Duration::from_secs(30)); group.bench_function("single_write", |b| { let mut key_counter = 0; b.iter(|| { let key = format!("latency_key_{:08}", key_counter).into_bytes(); key_counter += 1; store.put(black_box(key), black_box(value.clone()), None).unwrap(); }); }); group.finish(); } fn bench_read_latency(c: &mut Criterion) { let temp_dir = TempDir::new().unwrap(); let rocks_store = RocksStore::new(temp_dir.path()).unwrap(); let store = KvStore::new(rocks_store).unwrap(); let value = vec![b'x'; VALUE_SIZE]; // Pre-populate keys for i in 0..1000 { let key = format!("read_lat_key_{:08}", i).into_bytes(); store.put(key, value.clone(), None).unwrap(); } let mut group = c.benchmark_group("read_latency"); group.sample_size(1000); group.measurement_time(Duration::from_secs(30)); group.bench_function("single_read", |b| { let mut key_counter = 0; b.iter(|| { let key = format!("read_lat_key_{:08}", key_counter % 1000).into_bytes(); key_counter += 1; let _ = store.get(black_box(&key)).unwrap(); }); }); group.finish(); } criterion_group!( benches, bench_write_throughput, bench_read_throughput, bench_write_latency, bench_read_latency ); criterion_main!(benches);