From ed9e70956aac4721ea9d54c1531b5679f08e71dd Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Fri, 12 Sep 2025 15:40:15 +0200 Subject: [PATCH 1/2] stream: use new AsyncResource instead of bind The bind method uses ObjectDefineProperty that shows up in flamegraphs. This changes it to avoid the utility. Signed-off-by: Matteo Collina --- lib/internal/streams/end-of-stream.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/lib/internal/streams/end-of-stream.js b/lib/internal/streams/end-of-stream.js index 0db2d463b4c6d6..e73b201ae59b65 100644 --- a/lib/internal/streams/end-of-stream.js +++ b/lib/internal/streams/end-of-stream.js @@ -45,7 +45,7 @@ const { } = require('internal/streams/utils'); // Lazy load -let AsyncLocalStorage; +let AsyncResource; let addAbortListener; function isRequest(stream) { @@ -54,6 +54,14 @@ function isRequest(stream) { const nop = () => {}; +function bindAsyncResource(fn, type) { + AsyncResource ??= require('async_hooks').AsyncResource; + const resource = new AsyncResource(type); + return function (...args) { + return resource.runInAsyncScope(fn, this, ...args); + } +} + function eos(stream, options, callback) { if (arguments.length === 2) { callback = options; @@ -66,8 +74,9 @@ function eos(stream, options, callback) { validateFunction(callback, 'callback'); validateAbortSignal(options.signal, 'options.signal'); - AsyncLocalStorage ??= require('async_hooks').AsyncLocalStorage; - callback = once(AsyncLocalStorage.bind(callback)); + // Avoid AsyncResource.bind() because it calls ObjectDefineProperties which + // is a bottleneck here. + callback = once(bindAsyncResource(callback, 'STREAM_END_OF_STREAM')); if (isReadableStream(stream) || isWritableStream(stream)) { return eosWeb(stream, options, callback); From 7ebc47b5ae0e3215fc257a84102a54757206f834 Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Fri, 12 Sep 2025 16:16:45 +0200 Subject: [PATCH 2/2] fixup Signed-off-by: Matteo Collina --- lib/internal/streams/end-of-stream.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/internal/streams/end-of-stream.js b/lib/internal/streams/end-of-stream.js index e73b201ae59b65..850d4314139afd 100644 --- a/lib/internal/streams/end-of-stream.js +++ b/lib/internal/streams/end-of-stream.js @@ -57,9 +57,9 @@ const nop = () => {}; function bindAsyncResource(fn, type) { AsyncResource ??= require('async_hooks').AsyncResource; const resource = new AsyncResource(type); - return function (...args) { + return function(...args) { return resource.runInAsyncScope(fn, this, ...args); - } + }; } function eos(stream, options, callback) {