examples/code_room_consume_bench.rs
//! Times a FULL read of a workspace into a fresh code room: every member
//! consumed by the real driver, one line per commit with the phase split
//! (compile / read-back / second pass / delta / lake write) and the units
//! (compiled now / fresh), then the totals.
//!
//! ```text
//! NORNIR_MIMIR_DRIVER=/path/to/cargo-mimir-dump \
//! [NORNIR_MIMIR_TARGET=per-member] \
//! cargo run --release --no-default-features --features code-room \
//! --example code_room_consume_bench -- <builds-dir> <members-file>
//! ```
//! `<members-file>`: one member per line, `name source-dir branch sha` (the
//! source is a git clone holding `sha`). No feeds run (the dump pipeline
//! only). `<builds-dir>` should be empty for a cold read.
#[cfg(feature = "code-room")]
fn main() -> anyhow::Result<()> {
use std::time::Instant;
use nornir::code_room::CodeRoom;
use nornir::code_room::consumer_loop::{DriverDumpers, Event, Member, Request};
let mut args = std::env::args().skip(1);
let builds = std::path::PathBuf::from(args.next().expect("usage: code_room_consume_bench <builds-dir> <members-file>"));
// absolute, as on a server: the driver runs IN the member's tree
std::fs::create_dir_all(&builds)?;
let builds = builds.canonicalize()?;
let list = std::fs::read_to_string(args.next().expect("<members-file>"))?;
let members: Vec<Member> = list
.lines()
.map(str::trim)
.filter(|l| !l.is_empty() && !l.starts_with('#'))
.map(|l| {
let w: Vec<&str> = l.split_whitespace().collect();
Member { name: w[0].to_string(), source: w[1].into(), branch: Some(w[2].to_string()), head: w[3].to_string() }
})
.collect();
// every member's head must be its branch tip in its source: a stale line
// reads another commit than the file says (and leaves the member out of
// the super build) — refused, by name
let stale: Vec<String> = members
.iter()
.filter_map(|m| {
let branch = m.branch.as_deref().unwrap_or("HEAD");
let o = std::process::Command::new("git").arg("-C").arg(&m.source).args(["rev-parse", branch]).output().ok()?;
let tip = String::from_utf8_lossy(&o.stdout).trim().to_string();
(tip != m.head).then(|| format!("{} ({branch} is at {}, the file says {})", m.name, &tip[..tip.len().min(10)], &m.head[..m.head.len().min(10)]))
})
.collect();
if !stale.is_empty() {
anyhow::bail!("the members file is stale — fix these lines: {}", stale.join("; "));
}
let dumpers = DriverDumpers(nornir::code_room::driver::Settings::from_env().probe().map_err(|r| anyhow::anyhow!("{}", r.note))?);
let room = CodeRoom::new("bench", &builds);
let t0 = Instant::now();
let mut sums = [0u64; 8];
let mut on = |e: Event<'_>| match e {
Event::Member { member, behind } => eprintln!("[{:>6.1}s] {member}: {behind} commit(s) behind", t0.elapsed().as_secs_f32()),
Event::Commit { member, report: r } => {
let p = &r.phase_ms;
let d = p.dump_detail.unwrap_or_default();
for (i, v) in [p.dump, d.cargo_ms, d.read_ms, d.retry_ms, p.delta, p.commit, d.compiled, d.fresh].into_iter().enumerate() {
sums[i] += v;
}
println!(
"{member:<16} {:>8} ms dump {:>7} (cargo {:>7} read {:>6} retry {:>6}) delta {:>6} commit {:>6} units {:>5} compiled {:>5} fresh {:>5} recompiled {:>4} {} crates +{} {}{}",
r.ms, p.dump, d.cargo_ms, d.read_ms, d.retry_ms, p.delta, p.commit, d.units, d.compiled, d.fresh, d.recompiled, r.crates_dumped, r.rows_plus, r.status, r.error.as_deref().map(|e| format!(" — {e}")).unwrap_or_default()
);
}
Event::Std { toolchain, outcome, ms } => eprintln!("std of {toolchain}: {} in {ms} ms", if outcome.is_ok() { "ok" } else { "failed" }),
_ => {}
};
// `MIMIR_BENCH_ONLY=<member>`: every member's clone is made, one is read
let only = std::env::var("MIMIR_BENCH_ONLY").ok().filter(|v| !v.is_empty());
// `MIMIR_BENCH_AFFECTED=1`: only what a change reaches (`only: Affected`)
let affected = std::env::var("MIMIR_BENCH_AFFECTED").is_ok_and(|v| v == "1");
let report = room
.consume(&dumpers, &[], &Request { members: &members, only: only.as_deref(), affected, ..Default::default() }, &mut on)
.map_err(|r| anyhow::anyhow!("{}", r.note))?;
println!(
"TOTAL {} ms over {} member(s): dump {} (cargo {} read {} retry {}) delta {} commit {} · units compiled {} fresh {} · failed members {}",
t0.elapsed().as_millis(),
report.members.len(),
sums[0],
sums[1],
sums[2],
sums[3],
sums[4],
sums[5],
sums[6],
sums[7],
report.failed().len()
);
for c in &report.checked {
println!(" checked {}", c.line());
}
for m in &report.members {
if let Some(e) = &m.error {
println!(" {} FAILED: {e}", m.member);
}
}
Ok(())
}
#[cfg(not(feature = "code-room"))]
fn main() {
eprintln!("build with --features code-room");
}