nigig-org/crates/apps/nigig-traffic/tests/perf.rs
andodeki ac8f8aa002
Some checks failed
repo hygiene / hygiene (push) Has been cancelled
PDF engine / engine (push) Has been cancelled
PDF engine / makepad-integration (push) Has been cancelled
PDF engine / fuzz (push) Has been cancelled
nigig-build (CAD) / supply-chain (push) Has been cancelled
nigig-build (CAD) / cad-module (push) Has been cancelled
nigig-build (CAD) / full-crate-check (push) Has been cancelled
nigig-build (CAD) / cad-engine-coverage (push) Has been cancelled
nigig-build (CAD) / doc-workspace-coverage (push) Has been cancelled
nigig-build (CAD) / cad-widget-coverage (push) Has been cancelled
traffic / gates (push) Has been cancelled
traffic / nigig-traffic (push) Has been cancelled
traffic / supply-chain (push) Has been cancelled
doc-engine / engine (push) Has been cancelled
doc-engine / coverage (push) Has been cancelled
doc-engine / consumer (push) Has been cancelled
email / gates (push) Has been cancelled
email / email-domain (push) Has been cancelled
email / nigig-email (push) Has been cancelled
email / supply-chain (push) Has been cancelled
nigig-map / test (push) Has been cancelled
sms / gates (push) Has been cancelled
sms / robius-sms (push) Has been cancelled
sms / android (push) Has been cancelled
sms / nigig-sms (push) Has been cancelled
sms / supply-chain (push) Has been cancelled
spreadsheet / engine-coverage (push) Has been cancelled
spreadsheet / ui-controller-coverage (push) Has been cancelled
p2p-intel / engine (push) Has been cancelled
p2p-intel / notifications (push) Has been cancelled
p2p-intel / coverage (push) Has been cancelled
p2p-intel / makepad-app (push) Has been cancelled
p2p-intel / exchange-tab (push) Has been cancelled
Payment domain, storage, platform and UI / isolated-payment-tests (push) Has been cancelled
Payment domain, storage, platform and UI / payment-ui-tests (push) Has been cancelled
chore: sync full working tree to gitdab
Whole-tree sync: cad-core/cad-ui split sources, nigig-build
construction_frame migration, pdf port progress, mpesa/pay/uikit/doc
updates, workspace members/profiles/lock, CI workflows and reviews.
See individual file history for details.
2026-09-12 07:15:24 +03:00

88 lines
3.2 KiB
Rust

//! Perf baseline harness (plan Phase 6.3).
//!
//! Measures world-build and fixed-step tick costs and prints medians. The
//! timings are NOT asserted — wall-clock asserts are flaky by nature (HPC
//! ch.5.6). The sanity asserts only prove the sim actually ran (tick count,
//! phase transition, black-boxed state) so the optimizer cannot hollow the
//! loop. Run pinned on one machine and copy the table into
//! `docs/PERF_BASELINE.md` by hand:
//!
//! ```sh
//! cargo test -p nigig-traffic --test perf -- --test-threads=1 --nocapture
//! ```
use nigig_traffic::traffic::road::build_world_for;
use nigig_traffic::traffic::scenario::all;
use nigig_traffic::traffic::{Phase, TrafficWorld};
use std::hint::black_box;
use std::time::Instant;
fn median_us(mut samples: Vec<u128>) -> u128 {
samples.sort_unstable();
samples[samples.len() / 2]
}
#[test]
fn perf_print_baseline() {
let scenarios = all();
println!(
"=== nigig-traffic perf baseline ({} scenarios) ===",
scenarios.len()
);
// 1. World build per category (first scenario of each), 20 reps.
println!("--- build_world_for: median µs over 20 reps ---");
let mut seen_cats = Vec::new();
for s in scenarios {
if seen_cats.contains(&s.category) {
continue;
}
seen_cats.push(s.category);
let mut samples = Vec::with_capacity(20);
for _ in 0..20 {
let mut world = makepad_game_sim::GameWorld::new();
let mut next_id = 1u64;
let t0 = Instant::now();
let meta = build_world_for(&mut world, s, &mut next_id);
let us = t0.elapsed().as_micros();
// Touch the outputs so the build cannot be eliminated.
black_box(meta.finish_radius);
black_box(world.entities.len());
samples.push(us);
}
println!(
" {:<10} {:>6} µs",
format!("{:?}", s.category),
median_us(samples)
);
}
// 2. Fixed-step tick: 600 ticks per scenario, default (idle) input.
// Reports median per-tick µs across scenarios plus the slowest three.
println!("--- tick: 600 ticks/scenario, per-tick µs ---");
let mut per_tick: Vec<(&str, u128)> = Vec::new();
for (i, s) in scenarios.iter().enumerate() {
let mut world = TrafficWorld::new();
world.load_scenario(i);
let input = makepad_game_blocks::DriveInput::default();
let t0 = Instant::now();
for _ in 0..600 {
world.tick(&input);
}
let us = t0.elapsed().as_micros() / 600;
// Sanity: the sim really ran (intro is 60 ticks) and state escaped.
assert_eq!(world.run.tick, 600);
assert_eq!(world.run.phase, Phase::Driving);
black_box(world.run.score.total_points);
let _ = s;
per_tick.push((s.id, us));
}
per_tick.sort_by_key(|(_, us)| *us);
let mid = per_tick[per_tick.len() / 2].1;
println!(" scenarios: {}, median per-tick: {mid} µs", per_tick.len());
println!(" slowest 3:");
for (id, us) in per_tick.iter().rev().take(3) {
println!(" {id:<22} {us:>6} µs");
}
println!("=== end baseline ===");
}