Skip to content

Conversation

@gurgunday
Copy link
Member

Does the same optimization as #59873 for queueMicrotask

branch:

./node benchmark/run.js --filter queue-microtask process process/queue-microtask-breadth.js process/queue-microtask-breadth.js n=400000: 18,938,347.488090977 process/queue-microtask-depth.js process/queue-microtask-depth.js n=1200000: 35,862,646.06556887

main

./node benchmark/run.js --filter queue-microtask process process/queue-microtask-breadth.js process/queue-microtask-breadth.js n=400000: 5,198,220.087856157 process/queue-microtask-depth.js process/queue-microtask-depth.js n=1200000: 12,707,696.847598467

@nodejs-github-botnodejs-github-bot added needs-ci PRs that need a full CI run. process Issues and PRs related to the process subsystem. labels Nov 30, 2025
@gurgundaygurgunday added the performance Issues and PRs related to the performance of Node.js. label Nov 30, 2025
@gurgundaygurgunday changed the title process: stream: preserve AsyncLocalStorage on queueMicrotask only when neededprocess: preserve AsyncLocalStorage on queueMicrotask only when neededNov 30, 2025
@codecov
Copy link

codecovbot commented Nov 30, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 88.58%. Comparing base (6274eb7) to head (2f8776e).
⚠️ Report is 105 commits behind head on main.

Additional details and impacted files
@@ Coverage Diff @@## main #60913 +/- ## ========================================== + Coverage 88.55% 88.58% +0.02%  ========================================== Files 703 703 Lines 208291 208296 +5 Branches 40170 40166 -4 ========================================== + Hits 184443 184509 +66 + Misses 15874 15807 -67 - Partials 7974 7980 +6 
Files with missing linesCoverage Δ
lib/internal/process/task_queues.js100.00% <100.00%> (ø)

... and 48 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@FlarnaFlarna added the async_local_storage AsyncLocalStorage label Dec 1, 2025
@gurgunday
Copy link
MemberAuthor

cc @nodejs/performance

WDYT?

@H4adH4ad added the request-ci Add this label to start a Jenkins CI on a PR. label Dec 6, 2025
@H4ad
Copy link
Member

H4ad commented Dec 6, 2025

Before merging, some concerns raised in another PR with same changes:

One thing worth noting is that this would be a breaking change as currently the AsyncLocalStorage.bind(...) will always bind, even if there are no hooks or stores in use, but async_hooks could start listening at any time. In the current model you could start listening after the bind call there but before the callback is called and you would see the events. After this change you would not.
By @Qard

Would mind giving some thoughts on this one, @mcollina and @Qard?

Edit:
Benchmark: https://ci.nodejs.org/view/Node.js%20benchmark/job/benchmark-node-micro-benchmarks/1770/

@H4adH4ad added the semver-major PRs that contain breaking changes and should be released in the next major version. label Dec 6, 2025
@github-actionsgithub-actionsbot added request-ci-failed An error occurred while starting CI via request-ci label, and manual interventon is needed. and removed request-ci Add this label to start a Jenkins CI on a PR. labels Dec 6, 2025
@github-actions
Copy link
Contributor

Failed to start CI
 ⚠ No approving reviews found ✘ Refusing to run CI on potentially unsafe PR
https://github.com/nodejs/node/actions/runs/19980375054

@H4adH4ad removed the request-ci-failed An error occurred while starting CI via request-ci label, and manual interventon is needed. label Dec 6, 2025
@Qard
Copy link
Member

Qard commented Dec 6, 2025

@H4ad Yes, the same concern applies. It is, in my opinion, problematic that it was ever possible to start seeing events for a given task partway through its lifecycle rather than deciding at emit time if any of the events should be present. But that is certainly a breaking change and so should be marked as such. A desirable change, I think. But a breaking one nonetheless.

At the same time though, async_hooks is still marked as experimental, and AsyncLocalStorage no longer relies on it, so the break is likely a lot less critical. We may be able to allow it without a major bump. I'm not strongly opinionated either way.

Copy link
Member

@mcollinamcollina left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@mcollina
Copy link
Member

I'm ok in this being a minor, but I don't think we can backport it to 22.

@H4adH4ad added semver-minor PRs that contain new features and should be released in the next minor version. dont-land-on-v22.x PRs that should not land on the v22.x-staging branch and should not be released in v22.x. and removed semver-major PRs that contain breaking changes and should be released in the next major version. labels Dec 6, 2025
@H4ad
Copy link
Member

H4ad commented Dec 6, 2025

Benchmark result:

 confidence improvement accuracy (*) (**) (***) process/bench-env.js operation='delete' n=1000000 0.89 % ±5.64% ±7.51% ±9.77% process/bench-env.js operation='enumerate' n=1000000 1.65 % ±3.36% ±4.47% ±5.82% process/bench-env.js operation='get' n=1000000 -0.79 % ±1.68% ±2.24% ±2.91% process/bench-env.js operation='query' n=1000000 1.36 % ±2.64% ±3.51% ±4.57% process/bench-env.js operation='set' n=1000000 0.90 % ±3.45% ±4.59% ±5.98% process/bench-hrtime.js type='bigint' n=1000000 -1.11 % ±4.98% ±6.62% ±8.62% process/bench-hrtime.js type='diff' n=1000000 * -3.27 % ±3.21% ±4.27% ±5.57% process/bench-hrtime.js type='raw' n=1000000 -0.25 % ±3.02% ±4.02% ±5.24% process/coverage.js n=100000 0.03 % ±1.10% ±1.47% ±1.92% process/getActiveResourcesInfo.js n=100000 immediatesCount=10000 timeoutsCount=10000 requestsCount=10000 handlesCount=10000 -1.21 % ±5.47% ±7.28% ±9.48% process/memoryUsage.js n=100000 0.18 % ±0.41% ±0.55% ±0.71% process/next-tick-breadth-args.js n=10000000 0.05 % ±0.35% ±0.46% ±0.60% process/next-tick-breadth.js n=10000000 0.01 % ±0.75% ±1.00% ±1.30% process/next-tick-depth-args.js n=7000000 -0.79 % ±1.24% ±1.65% ±2.14% process/next-tick-depth.js n=7000000 0.48 % ±1.89% ±2.51% ±3.27% process/next-tick-exec-args.js n=4000000 -0.02 % ±8.70% ±11.57% ±15.06% process/next-tick-exec.js n=4000000 -0.03 % ±0.17% ±0.23% ±0.30% process/next-tick-loop-args.js loop=100 n=10000 -0.84 % ±2.36% ±3.14% ±4.08% process/next-tick-loop-args.js loop=100 n=20000 -0.43 % ±0.87% ±1.16% ±1.51% process/next-tick-loop-args.js loop=100 n=40000 0.35 % ±0.58% ±0.78% ±1.01% process/next-tick-loop-args.js loop=200 n=10000 0.29 % ±1.80% ±2.40% ±3.12% process/next-tick-loop-args.js loop=200 n=20000 0.29 % ±0.80% ±1.07% ±1.39% process/next-tick-loop-args.js loop=200 n=40000 -0.50 % ±0.64% ±0.85% ±1.10% process/next-tick-loop.js loop=100 n=10000 -0.73 % ±1.50% ±2.00% ±2.61% process/next-tick-loop.js loop=100 n=20000 -0.02 % ±1.85% ±2.46% ±3.21% process/next-tick-loop.js loop=100 n=40000 -0.24 % ±1.29% ±1.72% ±2.24% process/next-tick-loop.js loop=200 n=10000 -0.41 % ±1.30% ±1.73% ±2.26% process/next-tick-loop.js loop=200 n=20000 -0.27 % ±1.40% ±1.87% ±2.43% process/next-tick-loop.js loop=200 n=40000 0.19 % ±1.12% ±1.49% ±1.94% process/queue-microtask-breadth.js n=400000 *** 221.40 % ±5.59% ±7.53% ±9.98% process/queue-microtask-depth.js n=1200000 *** 137.38 % ±5.80% ±7.81% ±10.33% process/resourceUsage.js n=100000 -0.67 % ±2.84% ±3.77% ±4.91% Be aware that when doing many comparisons the risk of a false-positive result increases. In this case, there are 32 comparisons, you can thus expect the following amount of false-positive results: 1.60 false positives, when considering a 5% risk acceptance (*, **, ***), 0.32 false positives, when considering a 1% risk acceptance (**, ***), 0.03 false positives, when considering a 0.1% risk acceptance (***) 

Impressive 🚀

@H4adH4ad added the request-ci Add this label to start a Jenkins CI on a PR. label Dec 6, 2025
@github-actionsgithub-actionsbot removed the request-ci Add this label to start a Jenkins CI on a PR. label Dec 6, 2025
@nodejs-github-bot
Copy link
Collaborator

Copy link
Member

@mcollinamcollina left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@mcollinamcollina requested review from Qard and benglDecember 10, 2025 16:49
Copy link
Member

@QardQard left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with one small nit.

@Flarna
Copy link
Member

At the same time though, async_hooks is still marked as experimental, and AsyncLocalStorage no longer relies on it, so the break is likely a lot less critical. We may be able to allow it without a major bump. I'm not strongly opinionated either way.

The linked PR #59873 was marked semver major.

@Renegade334Renegade334 added the dont-land-on-v20.x PRs that should not land on the v20.x-staging branch and should not be released in v20.x. label Dec 12, 2025
@gurgundaygurgunday added commit-queue Add this label to land a pull request using GitHub Actions. commit-queue-squash Add this label to instruct the Commit Queue to squash all the PR commits into the first one. labels Dec 21, 2025
@nodejs-github-botnodejs-github-bot removed the commit-queue Add this label to land a pull request using GitHub Actions. label Dec 21, 2025
@nodejs-github-botnodejs-github-bot merged commit a65421a into nodejs:mainDec 21, 2025
94 of 95 checks passed
@nodejs-github-bot
Copy link
Collaborator

Landed in a65421a

@gurgundaygurgunday deleted the feat/optimize-enqueue branch December 21, 2025 01:13
MatricalDefunkt pushed a commit to MatricalDefunkt/node that referenced this pull request Dec 22, 2025
PR-URL: nodejs#60913 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Stephen Belanger <[email protected]> Reviewed-By: Gerhard Stöbich <[email protected]>
aduh95 pushed a commit that referenced this pull request Jan 9, 2026
PR-URL: #60913 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Stephen Belanger <[email protected]> Reviewed-By: Gerhard Stöbich <[email protected]>
aduh95 pushed a commit that referenced this pull request Jan 12, 2026
PR-URL: #60913 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Stephen Belanger <[email protected]> Reviewed-By: Gerhard Stöbich <[email protected]>
RafaelGSS pushed a commit that referenced this pull request Jan 13, 2026
PR-URL: #60913 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Stephen Belanger <[email protected]> Reviewed-By: Gerhard Stöbich <[email protected]>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

async_local_storageAsyncLocalStoragecommit-queue-squashAdd this label to instruct the Commit Queue to squash all the PR commits into the first one.dont-land-on-v20.xPRs that should not land on the v20.x-staging branch and should not be released in v20.x.dont-land-on-v22.xPRs that should not land on the v22.x-staging branch and should not be released in v22.x.needs-ciPRs that need a full CI run.performanceIssues and PRs related to the performance of Node.js.processIssues and PRs related to the process subsystem.semver-minorPRs that contain new features and should be released in the next minor version.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants

@gurgunday@H4ad@Qard@mcollina@nodejs-github-bot@Flarna@Renegade334