Merge pull request 'docs(clawhdf5): document DType variants, fix unresolved doc links' (#17) from sdlc-docs/clawhdf5-types-20260514-165210 into main
This commit is contained in:
@@ -0,0 +1,133 @@
|
||||
use clawhdf5_agent::ephemeral::{EphemeralConfig, EphemeralStore};
|
||||
use std::time::Instant;
|
||||
|
||||
fn main() {
|
||||
println!("=================================================================");
|
||||
println!(" Ephemeral Tier Latency Microbenchmark");
|
||||
println!("=================================================================\n");
|
||||
|
||||
// Warm up
|
||||
let mut store = EphemeralStore::new(EphemeralConfig {
|
||||
max_entries: 100_000,
|
||||
default_ttl_secs: 3600.0,
|
||||
track_access: true,
|
||||
});
|
||||
|
||||
// --- SET latency ---
|
||||
let n = 100_000;
|
||||
let start = Instant::now();
|
||||
for i in 0..n {
|
||||
store.set_text(
|
||||
&format!("key:{i}"),
|
||||
&format!("value-{i}-padding-text-for-realistic-size"),
|
||||
None,
|
||||
);
|
||||
}
|
||||
let set_elapsed = start.elapsed();
|
||||
let set_per_op = set_elapsed.as_nanos() as f64 / n as f64;
|
||||
println!(
|
||||
"SET {n} entries: {:.2} ms total ({:.0} ns/op {:.0} ops/sec)",
|
||||
set_elapsed.as_secs_f64() * 1000.0,
|
||||
set_per_op,
|
||||
1e9 / set_per_op
|
||||
);
|
||||
|
||||
// --- GET latency (hits) ---
|
||||
let start = Instant::now();
|
||||
for i in 0..n {
|
||||
let _ = store.get_text(&format!("key:{i}"));
|
||||
}
|
||||
let get_elapsed = start.elapsed();
|
||||
let get_per_op = get_elapsed.as_nanos() as f64 / n as f64;
|
||||
println!(
|
||||
"GET {n} hits: {:.2} ms total ({:.0} ns/op {:.0} ops/sec)",
|
||||
get_elapsed.as_secs_f64() * 1000.0,
|
||||
get_per_op,
|
||||
1e9 / get_per_op
|
||||
);
|
||||
|
||||
// --- GET latency (misses) ---
|
||||
let start = Instant::now();
|
||||
for i in 0..n {
|
||||
let _ = store.get_text(&format!("miss:{i}"));
|
||||
}
|
||||
let miss_elapsed = start.elapsed();
|
||||
let miss_per_op = miss_elapsed.as_nanos() as f64 / n as f64;
|
||||
println!(
|
||||
"GET {n} misses: {:.2} ms total ({:.0} ns/op {:.0} ops/sec)",
|
||||
miss_elapsed.as_secs_f64() * 1000.0,
|
||||
miss_per_op,
|
||||
1e9 / miss_per_op
|
||||
);
|
||||
|
||||
// --- DELETE latency ---
|
||||
let start = Instant::now();
|
||||
for i in 0..n {
|
||||
store.delete(&format!("key:{i}"));
|
||||
}
|
||||
let del_elapsed = start.elapsed();
|
||||
let del_per_op = del_elapsed.as_nanos() as f64 / n as f64;
|
||||
println!(
|
||||
"DEL {n} entries: {:.2} ms total ({:.0} ns/op {:.0} ops/sec)",
|
||||
del_elapsed.as_secs_f64() * 1000.0,
|
||||
del_per_op,
|
||||
1e9 / del_per_op
|
||||
);
|
||||
|
||||
// --- SET with embeddings ---
|
||||
let dim = 384;
|
||||
let emb: Vec<f32> = (0..dim).map(|i| (i as f32) * 0.001).collect();
|
||||
let n_emb = 10_000;
|
||||
let start = Instant::now();
|
||||
for i in 0..n_emb {
|
||||
store.set_with_embedding(
|
||||
&format!("emb:{i}"),
|
||||
&format!("embedding text {i}"),
|
||||
emb.clone(),
|
||||
None,
|
||||
);
|
||||
}
|
||||
let emb_elapsed = start.elapsed();
|
||||
let emb_per_op = emb_elapsed.as_nanos() as f64 / n_emb as f64;
|
||||
println!(
|
||||
"SET+EMB {n_emb} entries: {:.2} ms total ({:.0} ns/op {:.0} ops/sec)",
|
||||
emb_elapsed.as_secs_f64() * 1000.0,
|
||||
emb_per_op,
|
||||
1e9 / emb_per_op
|
||||
);
|
||||
|
||||
// --- Embedding search ---
|
||||
let query: Vec<f32> = (0..dim).map(|i| (i as f32) * 0.001 + 0.0001).collect();
|
||||
let start = Instant::now();
|
||||
let iters = 100;
|
||||
for _ in 0..iters {
|
||||
let _ = store.search_embedding(&query, 10);
|
||||
}
|
||||
let search_elapsed = start.elapsed();
|
||||
let search_per_op = search_elapsed.as_nanos() as f64 / iters as f64;
|
||||
println!(
|
||||
"SEARCH embedding 10K@384d: {:.2} ms/query ({:.0} µs avg)",
|
||||
search_per_op / 1e6,
|
||||
search_per_op / 1e3
|
||||
);
|
||||
|
||||
let stats = store.stats();
|
||||
println!(
|
||||
"\nStats: {} entries, {} bytes, {} hits, {} misses",
|
||||
stats.total_entries, stats.total_bytes, stats.hit_count, stats.miss_count
|
||||
);
|
||||
|
||||
println!("\n--- Redis comparison (typical single-node) ---");
|
||||
println!("Redis SET: ~25,000 ns/op");
|
||||
println!("Redis GET: ~25,000 ns/op");
|
||||
println!(
|
||||
"Ephemeral SET: {:.0} ns/op ({:.1}x faster)",
|
||||
set_per_op,
|
||||
25000.0 / set_per_op
|
||||
);
|
||||
println!(
|
||||
"Ephemeral GET: {:.0} ns/op ({:.1}x faster)",
|
||||
get_per_op,
|
||||
25000.0 / get_per_op
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user