Conversation
The resource created for each `process.nextTick()` call was an object literal with three computed symbol keys. V8 builds such literals from a boilerplate that only covers the static keys, so the symbol-keyed properties end up in a separate property array allocated per tick, and each computed-key store goes through the runtime. Construct the resource through a class instead, so that every tick object shares one map with all five fields in-object. process/next-tick-breadth-args.js: ~1.58M -> ~1.95M ops/s (+23%). Signed-off-by: Matteo Collina <hello@matteocollina.com>
mcollina
force-pushed
the
process-tickobject-class
branch
from
September 30, 2026 14:38
a5677ca to
d88d4a2
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #66415 +/- ##
==========================================
- Coverage 90.39% 90.37% -0.02%
==========================================
Files 792 792
Lines 275580 275690 +110
Branches 52840 52858 +18
==========================================
+ Hits 249104 249158 +54
- Misses 16897 16938 +41
- Partials 9579 9594 +15
🚀 New features to boost your workflow:
|
Contributor
|
Benchmark GHA (process / next-tick): https://github.com/nodejs/node/actions/runs/36746480545 Results
Benchmark results:
|
ronag
approved these changes
Sep 30, 2026
lpinca
approved these changes
Sep 30, 2026
addaleax
approved these changes
Sep 30, 2026
Collaborator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The resource created for each
process.nextTick()call was an object literal with three computed symbol keys. V8 builds such literals from a boilerplate that only covers the static keys (callback,args), so the three symbol-keyed properties end up in a separatePropertyArrayallocated per tick, and each computed-key store goes through the runtime.Constructing the resource through a class gives every tick object one map with all five fields in-object (64 bytes instead of 56 + 40), and plain monomorphic stores.
benchmark/compare.js --runs 10 --filter next-tick process:The two
breadthbenchmarks queue 10M ticks before draining anything, so all tick objects stay alive and the run is dominated by scavenges copying them (2–3 s of GC in a 3–5 s run). Onmainthe literal has an allocation site, and in some runs V8's allocation-site feedback pretenures the tick objects straight into old space: scavenges drop from ~85 to ~9 and the rate jumps from ~1.8M to ~3.5M ops/s. Class instances get no allocation-site feedback, so this PR sits at a steady ~2.4–3.5M with ~40–70 scavenges: faster thanmain's common regime, slower than its pretenured one, hence the noisy −8% average. Real workloads drain ticks the same turn they are scheduled, where pretenuring would be a pessimization; on an HTTP hello-world server this saves ~130 bytes per request (4 ticks) with no throughput change.🤖 Generated with Claude Code