Skip to content

perf (fetch): use less promises for ReadableStream#4457

Merged
Uzlopak merged 2 commits into
mainfrom
reduce-promises-from-ReadableStreamFrom
Aug 25, 2025
Merged

perf (fetch): use less promises for ReadableStream#4457
Uzlopak merged 2 commits into
mainfrom
reduce-promises-from-ReadableStreamFrom

Conversation

@Uzlopak

@Uzlopak Uzlopak commented Aug 24, 2025

Copy link
Copy Markdown
Contributor

before the test used 19 promises. now it uses only 13.

This relates to...

Rationale

Changes

Features

Bug Fixes

Breaking Changes and Deprecations

Status

@KhafraDev KhafraDev left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yes, undici might have less promises, but there's likely an equal number being created in node core. If we ignore node core, then what exactly are we testing?

@Uzlopak

Uzlopak commented Aug 25, 2025

Copy link
Copy Markdown
Contributor Author

@KhafraDev
That is not true. The amount of promises stays the same in core. With node core before 57 promises are generated, after it generates 51.

Before:

{
  'new ReadableStream (node:internal/webstreams/readablestream:256:30)': 2,
  'setupReadableByteStreamController (node:internal/webstreams/readablestream:3290:5)': 2,
  'setupReadableByteStreamController (node:internal/webstreams/readablestream:3289:3)': 2,
  'Object.start (/home/aras/workspace/undici/lib/core/util.js:612:19)': 1,
  'createDeferredPromise (/home/aras/workspace/undici/lib/util/promise.js:18:19)': 1,
  'readableStreamReaderGenericInitialize (node:internal/webstreams/readablestream:2163:30)': 1,
  'readAllBytes (/home/aras/workspace/undici/lib/web/fetch/util.js:1026:29)': 1,
  'new DefaultReadRequest (node:internal/webstreams/readablestream:790:20)': 3,
  'readAllBytes (/home/aras/workspace/undici/lib/web/fetch/util.js:1032:51)': 3,
  'TestContext.<anonymous> (/home/aras/workspace/undici/test/fetch/readable-stream-from.js:47:18)': 1,
  'node:internal/per_context/primordials:605:3': 1,
  'new SafePromise (node:internal/per_context/primordials:451:29)': 6,
  'node:internal/per_context/primordials:483:35': 2,
  'Test.run (node:internal/test_runner/test:1088:13)': 1,
  'Test.processPendingSubtests (node:internal/test_runner/test:763:18)': 1,
  'Promise.then (<anonymous>)': 4,
  'invokePromiseCallback (node:internal/webstreams/util:171:37)': 3,
  'pull (/home/aras/workspace/undici/lib/core/util.js:616:29)': 4,
  'pull (/home/aras/workspace/undici/lib/core/util.js:617:50)': 8,
  '[Symbol.asyncIterator] (/home/aras/workspace/undici/test/fetch/readable-stream-from.js:40:7)': 2,
  'readableByteStreamControllerCallPullIfNeeded (node:internal/webstreams/readablestream:3144:3)': 3,
  '[Symbol.asyncIterator] (/home/aras/workspace/undici/test/fetch/readable-stream-from.js:41:7)': 2,
  'pull (/home/aras/workspace/undici/lib/core/util.js:628:28)': 1,
  '[Symbol.asyncIterator] (/home/aras/workspace/undici/test/fetch/readable-stream-from.js:42:7)': 2
}

after:

{
  'new ReadableStream (node:internal/webstreams/readablestream:256:30)': 2,
  'setupReadableByteStreamController (node:internal/webstreams/readablestream:3290:5)': 2,
  'setupReadableByteStreamController (node:internal/webstreams/readablestream:3289:3)': 2,
  'createDeferredPromise (/home/aras/workspace/undici/lib/util/promise.js:18:19)': 1,
  'readableStreamReaderGenericInitialize (node:internal/webstreams/readablestream:2163:30)': 1,
  'readAllBytes (/home/aras/workspace/undici/lib/web/fetch/util.js:1026:29)': 1,
  'new DefaultReadRequest (node:internal/webstreams/readablestream:790:20)': 3,
  'readAllBytes (/home/aras/workspace/undici/lib/web/fetch/util.js:1032:51)': 3,
  'TestContext.<anonymous> (/home/aras/workspace/undici/test/fetch/readable-stream-from.js:47:18)': 1,
  'node:internal/per_context/primordials:605:3': 1,
  'new SafePromise (node:internal/per_context/primordials:451:29)': 6,
  'node:internal/per_context/primordials:483:35': 2,
  'Test.run (node:internal/test_runner/test:1088:13)': 1,
  'Test.processPendingSubtests (node:internal/test_runner/test:763:18)': 1,
  'invokePromiseCallback (node:internal/webstreams/util:171:37)': 3,
  'Object.pull (/home/aras/workspace/undici/lib/core/util.js:616:25)': 4,
  '[Symbol.asyncIterator] (/home/aras/workspace/undici/test/fetch/readable-stream-from.js:40:7)': 2,
  'Object.pull (/home/aras/workspace/undici/lib/core/util.js:616:32)': 4,
  'readableByteStreamControllerCallPullIfNeeded (node:internal/webstreams/readablestream:3144:3)': 3,
  'Promise.then (<anonymous>)': 4,
  '[Symbol.asyncIterator] (/home/aras/workspace/undici/test/fetch/readable-stream-from.js:41:7)': 2,
  '[Symbol.asyncIterator] (/home/aras/workspace/undici/test/fetch/readable-stream-from.js:42:7)': 2
}

@mcollina mcollina left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

lgtm - removing as many as possible would speed us up a tiny bit. Note that this code is functionally equivalent, so there is no downside here.

@KhafraDev

Copy link
Copy Markdown
Member

That is not true. The amount of promises stays the same in core. With node core before 57 promises are generated, after it generates 51.

What isn't true? The whole point is that if we are counting the number of promises in webstreams, we should include the ones from node core. After I made that comment I had to dig into the streams spec to find how the value was getting wrapped in a promise (in a sane world I would have expected startAlgorithm instanceof Promise ? startAlgorithm : Promise.resolve(startAlgorithm))

@Uzlopak

Uzlopak commented Aug 25, 2025

Copy link
Copy Markdown
Contributor Author

@KhafraDev

I cant write a test for created Promises in node core. I tried that but it is not working, because the created Promises are different on versions of nodejs. I could write tests based on the nodejs version, if this solves the blocking.

@Uzlopak Uzlopak merged commit 9358f06 into main Aug 25, 2025
35 of 36 checks passed
@Uzlopak Uzlopak deleted the reduce-promises-from-ReadableStreamFrom branch August 25, 2025 21:50
@github-actions github-actions Bot mentioned this pull request Sep 9, 2025
slagiewka pushed a commit to slagiewka/undici that referenced this pull request Feb 14, 2026
* perf: use less promises for ReadableStream

* remove test
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.

3 participants