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 to #10478 / #10479, fixed in PR #10592, which resolves an instanceof receiver per value kind
instead of assuming a heap pointer. That fixed real segfaults — instanceof crashed on 1-, 3- and 5-byte
inline strings (taking down ajv, and with it every fastify schema route) and Object.create(proto).constructor
returned a bogus value (crashing lodash's isEqual). The cost lands on constructor-shaped object allocation.
Measurement (from PR #10592, re-measured on a fresh host, not carried over from the pre-loss run)
fixture
instructions
bench_ctor_o.ts
+32.6%
bench_prim.ts
−5.7%
The +32.6% closely matches the +32.5% the original (lost) run recorded, so it reproduces across two
independent measurements on different hosts.
Attribution — it is NOT the EventEmitter subclass work in the same PR
bench_ctor_o never calls instanceof and never touches EventEmitter. The subclass-delegation change
shipped in the same PR was measured separately: +1.8% on a direct-EventEmitter-instance check, and a 63.9% reduction on mixed direct+subclass traffic (a subclass instance no longer burns through every
fallback probe on a guaranteed miss). The +32.6% belongs to the per-value-kind receiver resolution.
Why there is no honest "before" to compare against
The pre-fix binary segfaults on the inputs this path now handles correctly. There is no same-work
baseline; the old speed came from a fast path that was wrong. Only fix-vs-Node is meaningful.
The likely shape is the same one that made perf(runtime): stop re-deriving the receiver on every array push (−74%) #10414 worth −74.6%: per-call re-derivation of a receiver that
could be resolved once. Check whether the value-kind discrimination can be hoisted or cached per call site
rather than repeated per constructor invocation.
Accepted as a known cost (2026-09-18): the correctness fix ships, and this regression is handed to the
in-flight performance work rather than blocking it. There is deliberately no "restore the old speed" option —
the old speed came from the buggy path.
Highest-value lead recorded above: the per-call receiver re-derivation. #10414 was the same shape of defect in Array.prototype.push (receiver re-derived 6x per call) and fixing it was worth −74.6%. A monomorphic inline
cache on receiver kind at the call site is the obvious first thing to try, since these loops call the same
method on the same shape every iteration.
Activity
proggeramlug commentedon Sep 18, 2026
Accepted as a known cost (2026-09-18): the correctness fix ships, and this regression is handed to the
in-flight performance work rather than blocking it. There is deliberately no "restore the old speed" option —
the old speed came from the buggy path.
Highest-value lead recorded above: the per-call receiver re-derivation. #10414 was the same shape of defect in
Array.prototype.push(receiver re-derived 6x per call) and fixing it was worth −74.6%. A monomorphic inlinecache on receiver kind at the call site is the obvious first thing to try, since these loops call the same
method on the same shape every iteration.
perf(runtime): answer the Function.prototype identity probe from the …
perf(runtime): answer the Function.prototype identity probe from the …