nigig-org/crates/apps/nigig-traffic/docs/PERF.md
andodeki ac8f8aa002
Some checks failed
p2p-intel / engine (push) Waiting to run
p2p-intel / notifications (push) Waiting to run
p2p-intel / coverage (push) Waiting to run
p2p-intel / makepad-app (push) Waiting to run
p2p-intel / exchange-tab (push) Waiting to run
Payment domain, storage, platform and UI / isolated-payment-tests (push) Waiting to run
Payment domain, storage, platform and UI / payment-ui-tests (push) Waiting to run
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
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

3.4 KiB
Raw Permalink Blame History

nigig-traffic performance runbook (plan Phase 6)

Rule zero (HPC ch.1 "When to Optimize", ch.5): no optimization without a profile line pointing at it, and no number counts until it is in PERF_BASELINE.md. If it isn't in the baseline file, it didn't happen.

Live frame stats

The view collects tick + draw microseconds over a 300-sample window and reports p50/p95/p99 to the log (src/ui/game_view.rs: FrameStats). Collection is a few integer stores per frame; reporting only fires with:

NIGIG_TRAFFIC_STATS=1 cargo run -p nigig-traffic
# look for: traffic stats: tick us p50=.. p95=.. p99=.. (n=300)

Repeatable harness

cargo test -p nigig-traffic --test perf -- --test-threads=1 --nocapture

tests/perf.rs prints median build µs per category and per-tick µs over 600 ticks × every scenario. Timings are deliberately NOT asserted — wall-clock asserts are flaky by nature (HPC ch.5.6). The sanity asserts (tick count, Intro→Driving transition, black-boxed score) exist only so the optimizer cannot hollow the loop.

Methodology (HPC ch.5.6, condensed)

  • --test-threads=1, warmed runs, one machine, nothing else building. (Background cargo-makepad android jobs invalidated early readings here — check ps aux | grep rustc before trusting a number.)
  • Report medians, never means; re-run to check outlier stability. Outliers that move between runs are noise, not findings.
  • Debug profile numbers are for shape (which function, which scenario class), never for absolute budgets. Ship budgets come from release runs on the target device.

Statistical profiling

  • macOS: Instruments → Time Profiler, attach to target/debug/nigig-traffic while driving; look for step_world, draw_scene, evaluate, text shaping (shaper.rs), not the frame loop itself.
  • Linux: perf record -g + perf report. Top-down first, bottom-up to confirm callers.
  • Sampling finds the hot 3%; instrumentation lies about the rest. The FrameStats ring is the instrumentation — treat it as a tripwire, and reach for the sampler before changing code.

What the numbers said so far

See PERF_BASELINE.md. Headline: the tick is memory-latency-bound on tiny data (median ~1525µs debug, 47 scenarios), builds are single-digit µs. There is no compute hot spot to SIMD away — Phases 78 accordingly target lookups, allocations, and branches, not intrinsics.

Build environment notes (hard-won, do not re-learn)

  • RUSTC_WRAPPER=kache is exported on dev machines (~/.profile) but the kache binary may not exist — cargo then fails with could not execute process kache ... os error 2, surfacing in makepad-test runs as BuildStopped 101. Fix: ln -s sccache ~/.cargo/bin/kache, or standardize on sccache + SCCACHE_DIR in one place.
  • One target dir: the workspace root target/. Per-crate target/ dirs (a stale 2.2G one lived under nigig-traffic/ until Sep 2026) waste disk and split test artifacts across two trees. The makepad-test harness historically pointed CARGO_TARGET_DIR at the per-crate dir; keep it on the workspace root.
  • Release-vs-debug profile decision (opt-level 3 vs z for the game binary) is BLOCKED on a green workspace build — the fork rev bump broke compilation repo-wide (see Phase 9 notes in PERF_BASELINE.md). Measure both on the Phase-6 bench before choosing; do not pick on aesthetics.