commit 8a6cde7b8cd3e0c8c7ed704b78f89df57a99b45c
parent bfa30f771ee3069362c448511d73d1910a200510
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Sat, 13 Jun 2026 10:28:55 -0700
doc(perf): PERF-IDEAL.md WAVE 3 measured — -0.60% (cumulative -12.41%, 2.69x tcc) + A.3 misdiagnosis
Diffstat:
1 file changed, 44 insertions(+), 0 deletions(-)
diff --git a/doc/plan/PERF-IDEAL.md b/doc/plan/PERF-IDEAL.md
@@ -435,6 +435,50 @@ discipline holds):
- `pp_pull_into` 73.8M — **§C.3b** (don't materialize non-directive newlines) is
the structural follow-up.
+## Measured results — WAVE 3 (2026-06-13, 5 commits `fb17391c`..`bfa30f77`)
+
+The second-order levers, landed by 3 more parallel in-tree agents (type-hub /
+lexer-path / emit-hooks). **Diminishing returns, exactly as the docs warn
+second-order levers do:**
+
+| | Ir | vs tcc |
+|---|--:|--:|
+| after WAVE 1–2 | 1,796,553,239 | 2.71× |
+| **after WAVE 3** | **1,785,778,881** | **2.69×** |
+| WAVE 3 delta | −10,774,358 (−0.60%) | |
+| **cumulative (from `de8c3b62`)** | **−253,066,661 (−12.41%)** | **3.08× → 2.69×** |
+
+Gate: full 60-category byte-identity PASS, sqlite object still 2,216,680 B.
+
+| change | commit | measured |
+|---|---|---|
+| builtin pred_bits memo + §D.3b CgId-on-slot | `fb17391c`,`486575cf` | `api_type_pred` 66.8M → 61.9M (−4.9M) |
+| §A.3 punct cache (`struct Lexer` 1208→288 B) | `3e0e8146` | `__GI_memset` 28.7M → 26.5M (−2.2M) |
+| §C.3b drain non-directive newlines | `bfa30f77` | shows in `kit_arena_reset` (per-newline reset removed) |
+| §E.3 narrow register-only NT hooks | `d953be12` | ~3–5M in the `nd_binop`/cmp/convert crossing |
+
+**Honest correction (the re-profile earned it): §A.3 was mis-diagnosed.** The
+`lex_open_mem` 78.9M residual was assumed to be the per-open `memset` of the
+1208 B `struct Lexer`. It is **not** — `memset` is an out-of-line libc call, so
+shrinking the struct to 288 B only moved `__GI_memset` (−2.2M); `lex_open_mem`
+self stayed at **79.2M**. That 79M is genuine per-open work *other than* the
+memset (field init, the splice-fold loop control, `kit_source_add_memory`,
+`lex_catchup_splices`) and needs a fresh diagnosis before it can be cut. §A.3 was
+still a real −2.2M and shrank the struct 4.2×, but it did not touch the residual
+it targeted. Likewise the §D.2/§D.3b hub work moved `api_type_pred` only −5M — the
+per-call `id → entry` decode is more stubborn than the builtin-reclassify was.
+
+**The frontier is now genuinely hard.** The remaining top costs are the
+irreducible scan (`lex_next` 16.5%), `lex_open_mem` 79M (needs re-diagnosis —
+*not* the memset), `pool_intern_slice` 71.6M (probe side, measured ~0-Ir
+improvable), `src_next_raw_into` 86M + `pp_pull_into` 74M (per-token PP logic), and
+`api_type_pred`/`cg_type_get`/`api_unalias_type` decode (~115M, the next type
+lever is the id→entry decode itself). No remaining single structural lever of the
+WAVE-1 class (the O(M×N) rebuild, the redundant scalar pass) is visible — closing
+the last 2.69× → ~2× needs the **codesize track** (fewer emitted bytes, the
+multiplicative lever) and/or Track 4 (tcc's shared-token single-pass shape), not
+more per-op slimming.
+
## Appendix — claims verified against source (not docs)
- §A scalar splice loop + no NEON: `lex.c:156-157`, disasm of the profiled binary. ✓