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
{{ message }}
Repository navigation
perf: typed_array is 5.25x Node (8.66x instructions) — the corpus's worst row, and it was untracked until now #8496
typed_array is now the worst row in the corpus by a wide margin — 5.25x Node on wall, 8.66x on instructions retired. It was invisible to every sweep until today because it was
not in the corpus at all.
That is not an oversight in the benchmark's design — benchmarks/suite/bench_typed_array_untyped_access.ts
prints its own wall-clock timings, and the four-engine sweep's correctness gate is a
byte-exact stdout compare against the Node oracle, so a self-timing program can never join it.
I added gc-handoff/apps/typed_array.ts: identical workload (bcryptjs's Blowfish _encipher
shape, S/P reached through untyped params, ~4.27M calls), emitting only checksum:-821955270. Verified deterministic. The suite version remains the #5525
untyped/typed ratio metric; the corpus one is the regression tripwire.
For scale, the next-worst rows are iso_miss 1.94x and interp 1.51x. This one row is
roughly three times worse than anything else Perry runs.
What is already done — do not redo it
#8491 (closing #8485) landed a number_by_construction dataflow proof and moved this
workload −44.1% wall / −34.7% instructions / −52.6% peak RSS, with the untyped/typed ratio
improving 1.0438 → 1.0017. So the untyped and typed paths now cost nearly the same — the
remaining 5.25x is not a #5525-style untyped-vs-typed gap. Both paths are slow against
Node together.
Two further facts established during that work, worth not re-deriving:
The S-box element loads are already native. Optimized AArch64 shows ldr ..., [base, index, uxtw #2] — no NaN-box round trip, no per-element registry lookup.
The cost was the dynamic numeric envelope around them. perf(codegen): preserve numeric envelope proofs #8491 addressed the let n: number;-seeded-undefined shape. Whatever remains is a different part of that
envelope, or something else entirely.
Why this is the best available target
The instruction ratio (8.66x) is far above the wall ratio (5.25x), so the work is being
executed and there is no scheduling story to chase. Peak RSS is 0.06x Node — there is enormous
headroom to spend memory if that ever helped, though the standing project constraint is to
minimize RSS while keeping the best compute, so any RSS cost must be quantified and argued.
Suggested first step
Profile before hypothesizing. Compile with PERRY_KEEP_SYMBOLS=1 PERRY_DEBUG_SYMBOLS=1
(Perry strips output binaries; without these sample attributes everything to ???) and
aggregate over many runs. Find where the 8.66x actually goes now that #8491 has removed the
previously dominant leaves.
Fix is in #8540, rebased onto current main with no version bump. The optimization now removes shadow-root protocol only for source-declared Number/Int32 locals that also pass the annotation-agnostic whole-write Number proof; inferred Any/Unknown locals stay conservative. The original exact-once receiver CI regression is fixed, and the final optimized perry-codegen suite passes 1123/1123 locally. Measured typed_array retired instructions: 56.669 B -> 56.013 B (-1.16%); 20/20 corpus outputs remained byte-exact with checksum -821955270.
Activity
proggeramlug commentedon Aug 21, 2026
Fix is in #8540, rebased onto current
mainwith no version bump. The optimization now removes shadow-root protocol only for source-declaredNumber/Int32locals that also pass the annotation-agnostic whole-write Number proof; inferredAny/Unknownlocals stay conservative. The original exact-once receiver CI regression is fixed, and the final optimizedperry-codegensuite passes 1123/1123 locally. Measuredtyped_arrayretired instructions: 56.669 B -> 56.013 B (-1.16%); 20/20 corpus outputs remained byte-exact with checksum-821955270.