bench_embed/
bench_embed.rs1use kevy_embedded::{AppendFsync, Config, Store};
11use std::time::Instant;
12
13const KEYS: usize = 256;
14const VAL: &[u8] = b"value-payload-16";
15
16fn bench(label: &str, store: &Store, n: usize, keys: &[Vec<u8>]) {
17 for k in keys {
19 store.set(k, VAL).unwrap();
20 }
21
22 let t = Instant::now();
23 for i in 0..n {
24 store.set(&keys[i % KEYS], VAL).unwrap();
25 }
26 let set_s = t.elapsed().as_secs_f64();
27
28 let t = Instant::now();
29 let mut hits = 0usize;
30 for i in 0..n {
31 if store.get(&keys[i % KEYS]).unwrap().is_some() {
32 hits += 1;
33 }
34 }
35 let get_s = t.elapsed().as_secs_f64();
36 std::hint::black_box(hits);
37
38 println!(
39 "[{label:<13}] SET {:>10.0} ops/s GET {:>10.0} ops/s",
40 n as f64 / set_s,
41 n as f64 / get_s
42 );
43}
44
45fn main() {
46 let n: usize = std::env::var("KEVY_BENCH_N")
47 .ok()
48 .and_then(|s| s.parse().ok())
49 .unwrap_or(2_000_000);
50 let keys: Vec<Vec<u8>> = (0..KEYS).map(|i| format!("k{i}").into_bytes()).collect();
53
54 println!("kevy-embedded in-process throughput — single thread, n={n}, {KEYS} keys, {}B val", VAL.len());
55
56 let s1 = Store::open(Config::default().with_ttl_reaper_manual()).unwrap();
57 bench("in-memory", &s1, n, &keys);
58
59 let dir2 = std::env::temp_dir().join("kevy_embed_bench_everysec");
60 let _ = std::fs::remove_dir_all(&dir2);
61 let s2 = Store::open(
62 Config::default()
63 .with_persist(&dir2)
64 .with_ttl_reaper_manual()
65 .with_appendfsync(AppendFsync::EverySec),
66 )
67 .unwrap();
68 bench("aof-everysec", &s2, n, &keys);
69
70 let dir3 = std::env::temp_dir().join("kevy_embed_bench_always");
71 let _ = std::fs::remove_dir_all(&dir3);
72 let s3 = Store::open(
73 Config::default()
74 .with_persist(&dir3)
75 .with_ttl_reaper_manual()
76 .with_appendfsync(AppendFsync::Always),
77 )
78 .unwrap();
79 bench("aof-always", &s3, (n / 20).max(50_000), &keys);
82
83 bench_ttl_get("ttl GET (cached clk)", false, n, &keys); bench_ttl_get("ttl GET (fresh clk) ", true, n, &keys); drop((s1, s2, s3));
90 let _ = std::fs::remove_dir_all(&dir2);
91 let _ = std::fs::remove_dir_all(&dir3);
92}
93
94fn bench_ttl_get(label: &str, manual_reaper: bool, n: usize, keys: &[Vec<u8>]) {
98 let cfg = if manual_reaper {
99 Config::default().with_ttl_reaper_manual()
100 } else {
101 Config::default() };
103 let store = Store::open(cfg).unwrap();
104 let ttl = std::time::Duration::from_secs(3600); for k in keys {
106 store.set_with_ttl(k, VAL, ttl).unwrap();
107 }
108 let t = Instant::now();
109 let mut hits = 0usize;
110 for i in 0..n {
111 if store.get(&keys[i % KEYS]).unwrap().is_some() {
112 hits += 1;
113 }
114 }
115 std::hint::black_box(hits);
116 println!("[{label}] GET {:>10.0} ops/s", n as f64 / t.elapsed().as_secs_f64());
117}