use kevy_embedded::{AppendFsync, Config, Store};
use std::time::Instant;
const KEYS: usize = 256;
const VAL: &[u8] = b"value-payload-16";
fn bench(label: &str, store: &Store, n: usize, keys: &[Vec<u8>]) {
for k in keys {
store.set(k, VAL).unwrap();
}
let t = Instant::now();
for i in 0..n {
store.set(&keys[i % KEYS], VAL).unwrap();
}
let set_s = t.elapsed().as_secs_f64();
let t = Instant::now();
let mut hits = 0usize;
for i in 0..n {
if store.get(&keys[i % KEYS]).unwrap().is_some() {
hits += 1;
}
}
let get_s = t.elapsed().as_secs_f64();
std::hint::black_box(hits);
println!(
"[{label:<13}] SET {:>10.0} ops/s GET {:>10.0} ops/s",
n as f64 / set_s,
n as f64 / get_s
);
}
fn main() {
let n: usize = std::env::var("KEVY_BENCH_N")
.ok()
.and_then(|s| s.parse().ok())
.unwrap_or(2_000_000);
let keys: Vec<Vec<u8>> = (0..KEYS).map(|i| format!("k{i}").into_bytes()).collect();
println!("kevy-embedded in-process throughput — single thread, n={n}, {KEYS} keys, {}B val", VAL.len());
let s1 = Store::open(Config::default().with_ttl_reaper_manual()).unwrap();
bench("in-memory", &s1, n, &keys);
let dir2 = std::env::temp_dir().join("kevy_embed_bench_everysec");
let _ = std::fs::remove_dir_all(&dir2);
let s2 = Store::open(
Config::default()
.with_persist(&dir2)
.with_ttl_reaper_manual()
.with_appendfsync(AppendFsync::EverySec),
)
.unwrap();
bench("aof-everysec", &s2, n, &keys);
let dir3 = std::env::temp_dir().join("kevy_embed_bench_always");
let _ = std::fs::remove_dir_all(&dir3);
let s3 = Store::open(
Config::default()
.with_persist(&dir3)
.with_ttl_reaper_manual()
.with_appendfsync(AppendFsync::Always),
)
.unwrap();
bench("aof-always", &s3, (n / 20).max(50_000), &keys);
bench_ttl_get("ttl GET (cached clk)", false, n, &keys); bench_ttl_get("ttl GET (fresh clk) ", true, n, &keys);
drop((s1, s2, s3));
let _ = std::fs::remove_dir_all(&dir2);
let _ = std::fs::remove_dir_all(&dir3);
}
fn bench_ttl_get(label: &str, manual_reaper: bool, n: usize, keys: &[Vec<u8>]) {
let cfg = if manual_reaper {
Config::default().with_ttl_reaper_manual()
} else {
Config::default() };
let store = Store::open(cfg).unwrap();
let ttl = std::time::Duration::from_secs(3600); for k in keys {
store.set_with_ttl(k, VAL, ttl).unwrap();
}
let t = Instant::now();
let mut hits = 0usize;
for i in 0..n {
if store.get(&keys[i % KEYS]).unwrap().is_some() {
hits += 1;
}
}
std::hint::black_box(hits);
println!("[{label}] GET {:>10.0} ops/s", n as f64 / t.elapsed().as_secs_f64());
}