Files
brk/crates/brk_indexer/examples/indexer_read_speed.rs
2026-02-19 19:19:35 +01:00

104 lines
3.7 KiB
Rust

use std::{fs, path::Path, time::Instant};
use brk_error::Result;
use brk_indexer::Indexer;
use brk_types::Sats;
use vecdb::ReadableVec;
fn run_benchmark(indexer: &Indexer) -> (Sats, std::time::Duration, usize) {
let start = Instant::now();
let mut sum = Sats::ZERO;
let mut count = 0;
indexer.vecs.outputs.value.for_each(|value| {
sum += value;
count += 1;
});
let duration = start.elapsed();
(sum, duration, count)
}
fn main() -> Result<()> {
brk_logger::init(Some(Path::new(".log")))?;
let outputs_dir = Path::new(&std::env::var("HOME").unwrap()).join(".brk");
fs::create_dir_all(&outputs_dir)?;
println!("\n╔════════════════════════════════════════════════════════╗");
println!("║ BRK INDEXER SEQUENTIAL READ BENCHMARK ║");
println!("╚════════════════════════════════════════════════════════╝\n");
println!("Loading indexer from: {}", outputs_dir.display());
let indexer = Indexer::forced_import(&outputs_dir)?;
println!("Indexer loaded.\n");
// Warmup run
println!("🔥 Warmup run...");
let (sum, duration, count) = run_benchmark(&indexer);
println!(" Sum: {} sats", sum);
println!(" Time: {:.3}s", duration.as_secs_f64());
println!(" Count: {} values\n", count);
// Benchmark runs
let num_runs = 4;
let mut throughputs: Vec<f64> = Vec::new();
println!("📊 Running {} benchmark iterations...\n", num_runs);
for run in 1..=num_runs {
let (_, duration, count) = run_benchmark(&indexer);
let estimated_bytes = count * 8;
let throughput = estimated_bytes as f64 / duration.as_secs_f64() / (1024.0 * 1024.0);
let values_per_sec = count as f64 / duration.as_secs_f64() / 1_000_000.0;
throughputs.push(throughput);
println!(
"Run {:2}/{num_runs}: {:.3}s - {:>6.0} MB/s - {:>6.1}M values/s",
run,
duration.as_secs_f64(),
throughput,
values_per_sec
);
}
// Statistics
let mean = throughputs.iter().sum::<f64>() / throughputs.len() as f64;
let min = throughputs.iter().cloned().fold(f64::INFINITY, f64::min);
let max = throughputs
.iter()
.cloned()
.fold(f64::NEG_INFINITY, f64::max);
let variance =
throughputs.iter().map(|x| (x - mean).powi(2)).sum::<f64>() / throughputs.len() as f64;
let std_dev = variance.sqrt();
let cv = (std_dev / mean) * 100.0;
println!("\n╔════════════════════════════════════════════════════════╗");
println!("║ 📊 SUMMARY STATISTICS ║");
println!("╚════════════════════════════════════════════════════════╝\n");
println!(
"Values: {} ({:.2} MB)",
count,
(count * 8) as f64 / (1024.0 * 1024.0)
);
println!("Mean: {:.0} MB/s", mean);
println!("Min: {:.0} MB/s", min);
println!("Max: {:.0} MB/s", max);
println!("StdDev: {:.1} MB/s", std_dev);
println!("Variance: {:.1}%", cv);
if cv < 2.0 {
println!("✅ Excellent consistency");
} else if cv < 5.0 {
println!("✅ Good consistency");
} else {
println!("⚠️ High variance");
}
println!();
Ok(())
}