You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Follow-up from the #45 emit-backend gap audit. Three perf micro-optimizations were verified as real opportunities but are NEEDS_MEASUREMENT: every benchmark in the repo (test/perf-bench.ts, test/emit-parser-bench.ts, test/bench.ts, test/head-to-head.ts) reads the pinned /tmp/ts-repo corpus, so the project's measure-first perf discipline can't be satisfied without it. Each should be implemented byte-identical (proven by the now-CI-wired parity gates) and landed only if the corpus bench shows a win.
D1 — inline alt has no predictive dispatch
matchInto's case 'alt' (an altinside a seq) emits a naive shared-save try-each-arm, while rule-level longest-match already has altMaskDispatch (bitmask) + SECOND refinement. FIRST-disjoint inline alts could switch-dispatch on the first token (ordered first-match is preserved when arms are FIRST-disjoint); 2-arm alts could pick the arm from the first token with no save/restore. Scale: typescript.ts ~78 alt(, javascript.ts ~43. Most substantive of the three.
C3 — SURG_ELEM table is too narrow
The node-surgery element table is built only for a pure seq/group around exactly one */+ with no alt/opt/?/multiple reps, so any list rule with an optional element or alternative (trailing comma, member list with modifiers, union body) gets no surgery and every edit inside it takes a full adoption re-parse. The audit suggests opts around the rep region may be admissible via the rowKC watermark argument — but the agent flagged uncertainty about whether the watermark check handles a [rep*, optional] kid structure, so this is the riskiest of the three and needs the surgery layout invariants worked out + exhaustive-edits confirmation (with the relaxed path asserted to fire).
B5 — lexKwT call-site length sentinel
The identifier hot path scans [pos+1, p) in the char loop, then lexKwT re-checks length-bounded keyword candidates. A top-level LX_MAXKW constant could short-circuit the call ((p - pos) > LX_MAXKW ? 0 : lexKwT(...)). Caveat found during the audit:lexKwT already bails on its first statement (if (n < minKw || n > maxKw) return 0), so the only saving is the function-call overhead for long identifiers — whether that helps depends on whether V8 already inlines lexKwT (it has a large switch). Smallest expected win; measure before bothering.
All three were left out of #45 / PR #53 precisely because landing an unmeasured perf change would violate the repo's measure-first rule, not because they aren't worth doing.
Note discovered while wiring the full-corpus emit-parity job (PR #53): D1 also has a correctness/parity payoff, not just perf. The emitter's naive inline-alt try-each-arm explores an arm the interpreter prunes, so on rare rejected inputs (e.g. const { 0n: f } = arr;) the two engines reach a different farthest-exploration token — identical CST and identical primary error, but a different [farthest: …] hint. PR #53 handles this by pinning the primary error and treating the hint as a benign Layer-B artifact. Giving the emitter the interpreter's inline-alt dispatch (D1) would prune the same arm and restore exact [farthest: …] parity as a side effect.
Measured all three against the pinned TS corpus (now that the corpus blocker is gone). The emitted parser is already ~2.3 ms / ~14× the interpreter on the bench files, and none of the three justifies landing.
B5 — lexKwT call-site length sentinel. lexKwT is 3.3% self-time in the emit profile, but the sentinel only skips the call for runs outside [minKw, maxKw], and lexKwT already bails on its first statement (if (n < minKw || n > maxKw) return 0). Tokenize-only A/B (best-of-7, N=200): 1.224 ms with the sentinel vs 1.226 ms without — no measurable change. V8 evidently handles the early-exit efficiently, exactly the caveat noted when filing. Byte-identical, but zero gain → not landed.
D1 — inline-alt predictive dispatch. Implemented a FIRST-guard on every seq-internal alt arm (recovering || _q(save), byte-identical incl. maxPos — a skipped arm fails at its first token without advancing; 869 guards emitted; full-corpus CST parity held). Same-process interleaved A/B (best-of-8 rounds × 6): baseline 2.312 ms vs D1 2.300 ms = 0.5% faster (noise floor), and the emitted parser grows +3% (+35 KB). The profile explains it: inline-alt FIRST-dispatch (_q) is 0.02% and the arm matchers <1% each — not a hotspot. A 3% bigger artifact for a noise-floor speedup isn't worth it → not landed.
C3 — SURG_ELEM relaxation (sep-list surgery). The list-shaped rules excluded from surgery are the sep-based comma-lists (call args, array/object literals, params). Measured edit latency vs list size:
array-literal (sep of Expr): 0.039 ms @50 → 0.046 @200 → 0.145 @800 — O(N) adoption.
union-type (sep of Type): flat ~0.01 ms — already fast (routes through the Pratt/memo path, not adoption).
block many(Stmt) (surgery-eligible): flat ~0.007 ms — the O(1) baseline.
So the win is real only for large Expr comma-lists, and sub-millisecond except for pathologically large (generated) literals. Capturing it needs sep-aware surgery — a splice that handles the interleaved delimiters — which directly contradicts the engine's documented soundness invariant for surgery (the SURG_ELEM build comment: "a longest-match arm (or lookahead) at the container's OWN level may probe into the rep zone without any kid row owning the read, which would break the prefix-keep watermark argument"). That's a high-risk rewrite of the most delicate code for a marginal, rarely-hit gain.
Closing as a measured wontfix: the engine is already highly optimized, and these three micro-optimizations are either zero-gain (B5), noise-floor-for-bigger-artifact (D1), or marginal-gain-against-a-soundness-invariant (C3). Reopen if large-literal incremental latency becomes a real product concern — C3's path is the one with a (modest) payoff, gated by exhaustive-edits as the soundness arbiter.
Activity
test: pin the primary reject message, not the farthest-exploration hi…
johnsoncodehk commentedon Jun 20, 2026
Note discovered while wiring the full-corpus
emit-parityjob (PR #53): D1 also has a correctness/parity payoff, not just perf. The emitter's naive inline-alttry-each-arm explores an arm the interpreter prunes, so on rare rejected inputs (e.g.const { 0n: f } = arr;) the two engines reach a different farthest-exploration token — identical CST and identical primary error, but a different[farthest: …]hint. PR #53 handles this by pinning the primary error and treating the hint as a benign Layer-B artifact. Giving the emitter the interpreter's inline-alt dispatch (D1) would prune the same arm and restore exact[farthest: …]parity as a side effect.johnsoncodehk commentedon Jun 20, 2026
Measured all three against the pinned TS corpus (now that the corpus blocker is gone). The emitted parser is already ~2.3 ms / ~14× the interpreter on the bench files, and none of the three justifies landing.
B5 —
lexKwTcall-site length sentinel. lexKwT is 3.3% self-time in the emit profile, but the sentinel only skips the call for runs outside[minKw, maxKw], and lexKwT already bails on its first statement (if (n < minKw || n > maxKw) return 0). Tokenize-only A/B (best-of-7, N=200): 1.224 ms with the sentinel vs 1.226 ms without — no measurable change. V8 evidently handles the early-exit efficiently, exactly the caveat noted when filing. Byte-identical, but zero gain → not landed.D1 — inline-
altpredictive dispatch. Implemented a FIRST-guard on every seq-internal alt arm (recovering || _q(save), byte-identical incl. maxPos — a skipped arm fails at its first token without advancing; 869 guards emitted; full-corpus CST parity held). Same-process interleaved A/B (best-of-8 rounds × 6): baseline 2.312 ms vs D1 2.300 ms = 0.5% faster (noise floor), and the emitted parser grows +3% (+35 KB). The profile explains it: inline-alt FIRST-dispatch (_q) is 0.02% and the arm matchers <1% each — not a hotspot. A 3% bigger artifact for a noise-floor speedup isn't worth it → not landed.C3 —
SURG_ELEMrelaxation (sep-list surgery). The list-shaped rules excluded from surgery are thesep-based comma-lists (call args, array/object literals, params). Measured edit latency vs list size:sepof Expr): 0.039 ms @50 → 0.046 @200 → 0.145 @800 — O(N) adoption.sepof Type): flat ~0.01 ms — already fast (routes through the Pratt/memo path, not adoption).many(Stmt)(surgery-eligible): flat ~0.007 ms — the O(1) baseline.So the win is real only for large Expr comma-lists, and sub-millisecond except for pathologically large (generated) literals. Capturing it needs sep-aware surgery — a splice that handles the interleaved delimiters — which directly contradicts the engine's documented soundness invariant for surgery (the SURG_ELEM build comment: "a longest-match arm (or lookahead) at the container's OWN level may probe into the rep zone without any kid row owning the read, which would break the prefix-keep watermark argument"). That's a high-risk rewrite of the most delicate code for a marginal, rarely-hit gain.
Closing as a measured wontfix: the engine is already highly optimized, and these three micro-optimizations are either zero-gain (B5), noise-floor-for-bigger-artifact (D1), or marginal-gain-against-a-soundness-invariant (C3). Reopen if large-literal incremental latency becomes a real product concern — C3's path is the one with a (modest) payoff, gated by
exhaustive-editsas the soundness arbiter.