Performance (NFR-07 / ADR-011)
Performance is a first-class pillar, not a Later learning-only note. That does not authorize fake benches.
Rules
- A latency, cycle, or “faster than” sentence is a claim. It needs a probe in the honesty ledger.
- Optimize only after a probe shows a cost. Do not rewrite the scheduler or heap “for speed” on a hunch.
- QEMU
virtnumbers are one environment. They are not a Raspberry Pi probe and not a published SPEC run.
Baseline probe (this tree)
CNTPCT_EL0 is already used to timeout the M5 timer observe window. The pillars ratchet (when landed) measures a fixed trivial loop:
- Serial marker
perf: cntpct delta=<n>(fail closed onperf: probe missed). #[test_case]asserts the counter advanced.
That probe proves the physical counter is readable and moves. It does not claim a microsecond budget, interrupt latency, or a comparison to other kernels.
IRQ-to-handler probe (this tree)
When CNTP fires, the handler records CNTPCT − CNTP_CVAL before rearm. After several ticks the hello kernel prints:
- Serial marker
perf: irq-delta min=<a> max=<b> spread=<b-a> n=<n>(fail closed onperf: irq-delta missed). #[test_case]asserts samples exist andmax >= min.
That is a spread of IRQ-to-handler counter deltas on this QEMU virt guest. It is not a latency budget, not “faster than X,” and not a published bench. QEMU TCG jitter is one environment.
Host debug ELF size (NFR-08, this tree)
scripts/qemu-smoke.sh prints the host byte size of target/aarch64-ctos/debug/ctos after cargo build:
- Host marker
perf: elf-size bytes=<n>(fail closed if missing or< 4096). - This is a measurement, not a size budget and not a “smaller is better” claim.
It does not time QEMU boot.
Boot-to-ready CNTPCT (NFR-08, this tree)
kernel_main samples CNTPCT_EL0 after paging::init (MMU + D-cache on) and again after Hello World! (init complete):
- Serial marker
perf: boot-delta ticks=<n>(fail closed onperf: boot-delta missed). #[test_case]asserts a sample exists and the counter advanced.
That is kernel_main-entry to after-init on this QEMU virt guest. It is not a latency budget, not QEMU startup time, not a published bench, and not criterion.
OS/app slot disconnect (A9) — expected shape, not a bench
A9 #48 would load a separate app payload after the OS image (immutability.md, site measure.md). That is Planned after Track A ABI/loader. Today is still one linked ELF. There is no Verified delta. Do not invent a “faster/slower than linked-in” number.
| Class | What we expect (hypothesis, unmeasured) | Honesty |
|---|---|---|
| Costs | Extra boot/load work; each SVC crossing; ASID/TTBR0 switches into the app map; optional COW later if payloads are shared | Cost only after a probe. Not a budget. |
| Neutral / wins | Steady EL0 compute (once mapped) should look like today’s standing stub, not like a new ISA. Smaller OS updates are an operational win (rebuild kernel without apps), not a CNTPCT win | Operational ≠ measured latency. |
| Gate | Keep perf: boot-delta. Add a new app-load CNTPCT probe (perf: app-load or similar) when the loader exists. Fail closed on miss | Marker does not exist today. |
Until that app-load probe prints on a two-artifact boot, A9 performance stays Planned. QEMU TCG jitter is still one lab. No criterion crate. No “slot disconnect is free.”
Later probes (Planned)
- A tighter “first instruction of
_start” sample if someone maps a.dataslot that BSS-clear will not wipe. - App-load CNTPCT (A9) — only after a real loader; see the table above. Site KPI page: measure.md. Do not invent a percent.
Do not add a host criterion crate or a “bench.yml” that prints invented numbers.