use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::time::{Duration, Instant};
use holt::{Tree, TreeConfig};
const KEYS: u32 = 10_000;
const VALUE_LEN: usize = 64;
fn populate_tree() -> (Tree, tempfile::TempDir) {
let dir = tempfile::tempdir().unwrap();
let mut cfg = TreeConfig::new(dir.path());
cfg.buffer_pool_size = 128; let tree = Tree::open(cfg).unwrap();
for i in 0..KEYS {
let k = format!("key/{i:08}");
let v = vec![(i & 0xFF) as u8; VALUE_LEN];
tree.put(k.as_bytes(), &v).unwrap();
}
tree.checkpoint().unwrap();
(tree, dir)
}
fn run_reader_bench(tree: &Tree, threads: usize, duration: Duration) -> u64 {
let stop = Arc::new(AtomicBool::new(false));
let mut handles = Vec::with_capacity(threads);
for t in 0..threads {
let tree = tree.clone();
let stop = Arc::clone(&stop);
handles.push(std::thread::spawn(move || -> u64 {
let mut i: u32 = (t as u32).wrapping_mul(KEYS / threads as u32);
let mut ops: u64 = 0;
while !stop.load(Ordering::Relaxed) {
let k = format!("key/{:08}", i % KEYS);
let _v = tree.get(k.as_bytes()).unwrap();
i = i.wrapping_add(1);
ops += 1;
}
ops
}));
}
std::thread::sleep(Duration::from_millis(50));
let t0 = Instant::now();
std::thread::sleep(duration);
stop.store(true, Ordering::Relaxed);
let mut total: u64 = 0;
for h in handles {
total += h.join().unwrap();
}
let _ = t0;
total
}
#[test]
#[ignore]
fn hybrid_latch_read_scaling() {
let (tree, _dir) = populate_tree();
let measure = Duration::from_secs(2);
println!("\n=== HybridLatch read scaling ({KEYS} keys × {VALUE_LEN} B values) ===\n");
println!(
"{:<10} {:>14} {:>14} {:>10}",
"threads", "total_ops", "ops/sec", "scaling"
);
println!("{}", "-".repeat(56));
let mut base_throughput: Option<u64> = None;
for &threads in &[1usize, 2, 4, 8, 16] {
let ops = run_reader_bench(&tree, threads, measure);
let ops_per_sec = (ops as f64 / measure.as_secs_f64()) as u64;
let scaling = base_throughput.map_or(1.0, |b| ops_per_sec as f64 / b as f64);
if base_throughput.is_none() {
base_throughput = Some(ops_per_sec);
}
println!(
"{:<10} {:>14} {:>14} {:>9.2}x",
threads, ops, ops_per_sec, scaling,
);
}
println!();
let ops = run_reader_bench(&tree, 1, Duration::from_millis(200));
assert!(ops > 100, "1-thread bench measured suspiciously few ops");
}