Skip to content

perf(arrays): inline compact primitives - #77

Merged
BridgeAR merged 7 commits into
mainfrom
BridgeAR/2026-10-13-stringify-primitives
Oct 15, 2026
Merged

BridgeAR merged 7 commits into
mainfrom
BridgeAR/2026-10-13-stringify-primitives

Conversation

@BridgeAR

Copy link
Copy Markdown
Owner

Compact arrays pay recursive dispatch and index conversion for strings, finite numbers, and booleans.
Safe mode retains per-element exception handling.

A four-number array uses 101 ns instead of 133 ns, a 24% CPU reduction on Node 26.3.1 (V8 14.6.202.34-node.20).
Measurements use 50,000 warmup calls and seven alternating trials, with the fastest and slowest trials removed.
Four-object arrays use about 5% more CPU in both confirmation runs.

Drive-by fix: Mark intentional invalid-option assertions for TypeScript.

@BridgeAR
BridgeAR force-pushed the BridgeAR/2026-10-13-stringify-primitives branch from f86ee76 to 39cbfad Compare October 13, 2026 05:51
A four-number array uses 101 ns instead of 133 ns on Node 26.3.1
(V8 14.6.202.34-node.20), a 24% CPU reduction. Measurements use 50,000 warmup
calls and seven alternating trials, with the fastest and slowest removed.
Four-object arrays use about 5% more CPU in both confirmation runs.
Safe mode retains per-element exception handling.

Drive-by fix: Mark intentional invalid-option assertions for TypeScript.
Compact object arrays pay primitive checks before recursive serialization,
which adds overhead to the existing object path.

Four-number arrays use 69.8 ns instead of 75.4 ns on Node 26.3.1
(V8 14.6.202.34-node.20), a 7.4% reduction. Measurements use 100,000 warmup
calls and seven alternating trials, with the fastest and slowest removed.

Safe mode must catch primitive failures per value so an oversized string
does not replace its containing array.
On Node 26.3.1 (V8 14.6.202.34-node.20), a four-number array with
indentation takes 82.8 ns instead of 100.7 ns, an 18% CPU reduction.
Measurements use 100,000 warmup calls and seven alternating trials of
200,000 calls, with the fastest and slowest results removed.

Function replacers already catch failures per value in safe mode.
Reusing that boundary avoids a second wrapper around primitive formatting.
@BridgeAR
BridgeAR force-pushed the BridgeAR/2026-10-13-stringify-primitives branch from 39cbfad to dc389b9 Compare October 13, 2026 06:35
TAP 21 and newer processinfo releases cannot support the Node.js 18 test
matrix. TypeScript 6 retains legacy Node resolution and works with TAP's
current TypeScript loader.
Against main, the comparison fixture increases from 68,305 to 76,684 ops/sec
on Node.js 26.3.1 (V8 14.6.202.34-node.20), with 50,000 warmup calls and seven
two-second trials excluding the fastest and slowest results.

Some deep-object benchmark cases measure up to 3.1% slower. Shared primitive
handling reduces published source size by 5.2% while preventing the implementations
from diverging.
The primitive error matrix encodes a maximum-length string 18 times.
On Node.js 18.20.8 (V8 10.2.154.26-node.39), that takes 22.1 seconds.
Slower CI runners reach the 30-second timeout before the suite completes.

The mode matrix uses a controlled RangeError at the native escaping
boundary. Existing tests still exercise the real string limit. The full
Node.js 18 suite takes 4.1 seconds after a clean install.
Array replacers cannot change a primitive root's output. Skip their
preprocessing, including getter and iterator reads, for these inputs.

A numeric root with an eight-entry array replacer takes 8.4 ns instead of
97.4 ns on Node 26.3.1 (V8 14.6.202.34-node.20). This averages two fresh
processes with seven alternating trials after 50,000 warmup calls,
discarding the fastest and slowest trials.
@BridgeAR
BridgeAR marked this pull request as ready for review October 15, 2026 07:55
@BridgeAR
BridgeAR merged commit bdd585f into main Oct 15, 2026
5 checks passed
@BridgeAR
BridgeAR deleted the BridgeAR/2026-10-13-stringify-primitives branch October 15, 2026 07:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant