Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/nornir

examples/mimir-light-bench.rs

//! LIGHT-arm Mimir bench runner — the working-box-safe subset.
//!
//! The full `nornir-bench` suite (105 benchers, up to 100k-row appends and 10M-key
//! Ragnar builds) is a HEAVY sweep and is owed to an idle machine (heavy-bench
//! law). This runner executes only the **small** arms named on the command line
//! (or `NORNIR_BENCH_ONLY`, comma-separated substrings) so an optimize-loop cycle
//! can measure a single populate path on a developer box without burning it.
//!
//! It reuses the SAME registry (`inventory` + `register_bench!`) and the SAME
//! `Bencher::run()` bodies as `nornir-bench` — no forked fixtures, no second
//! definition of the work being timed — so a number here is directly comparable
//! to that arm's row in the authoritative run.
//!
//!     cargo run --release --example mimir-light-bench -- iceberg_commit_ sql_point_500
//!
//! Prints one JSON line per bench (`{"name":…,"metrics":{…}}`) plus a compact
//! human table on stderr. `reps` (env `MIMIR_BENCH_REPS`, default 3) repeats each
//! arm and reports the MEDIAN, since a single fsync-bound run on a busy desktop
//! is noisy.

use anyhow::Result;
use nornir::bench::api::{Bencher, BencherRegistration};

fn main() -> Result<()> {
    let mut pats: Vec<String> = std::env::args().skip(1).collect();
    if pats.is_empty() {
        pats = std::env::var("NORNIR_BENCH_ONLY")
            .unwrap_or_default()
            .split(',')
            .map(|s| s.trim().to_string())
            .filter(|s| !s.is_empty())
            .collect();
    }
    if pats.is_empty() {
        eprintln!("usage: mimir-light-bench <id-substring>…  (or NORNIR_BENCH_ONLY=…)");
        std::process::exit(2);
    }
    let reps: usize = std::env::var("MIMIR_BENCH_REPS")
        .ok()
        .and_then(|v| v.parse().ok())
        .unwrap_or(3);

    let mut chosen: Vec<&'static dyn Bencher> = inventory::iter::<BencherRegistration>()
        .map(|r| (r.make)())
        .filter(|b| pats.iter().any(|p| b.id().contains(p.as_str())))
        .collect();
    chosen.sort_by_key(|b| b.id());
    if chosen.is_empty() {
        eprintln!("mimir-light-bench: no registered bench id matched {pats:?}");
        std::process::exit(2);
    }

    for b in chosen {
        // Repeat and keep the MEDIAN result — the run bodies are self-contained
        // (fresh tempdir warehouse per run), so reps are independent samples.
        let mut runs: Vec<nornir::bench::BenchResult> = Vec::with_capacity(reps);
        for _ in 0..reps {
            runs.push(b.run()?);
        }
        // Sort by the arm's headline throughput metric (the sole `*_per_sec`).
        let key = |r: &nornir::bench::BenchResult| -> f64 {
            r.metrics
                .iter()
                .find(|(k, _)| k.ends_with("_per_sec"))
                .and_then(|(_, v)| v.as_f64())
                .unwrap_or(0.0)
        };
        runs.sort_by(|a, c| {
            key(a)
                .partial_cmp(&key(c))
                .unwrap_or(std::cmp::Ordering::Equal)
        });
        let med = &runs[runs.len() / 2];
        eprintln!(
            "{:<48} {:>12.1}/s  p50={:>9.1}us p99={:>9.1}us   (median of {reps})",
            med.name,
            key(med),
            med.metrics
                .get("p50_us")
                .and_then(|v| v.as_f64())
                .unwrap_or(0.0),
            med.metrics
                .get("p99_us")
                .and_then(|v| v.as_f64())
                .unwrap_or(0.0),
        );
        println!("{}", serde_json::to_string(med)?);
    }
    Ok(())
}