stream: speed up async iteration over WHATWG byte streams#64291
Open
mcollina wants to merge 2 commits into
Open
stream: speed up async iteration over WHATWG byte streams#64291mcollina wants to merge 2 commits into
mcollina wants to merge 2 commits into
Conversation
Collaborator
|
Review requested:
|
for await / reader.read() loops over byte streams were ~4x slower than over default streams. Three per-chunk costs, none required by the spec: - ArrayBufferViewGetBuffer/ByteLength/ByteOffset went through ReflectGet(view.constructor.prototype, ...), a reflective get that is ~3.5x slower than the original prototype getters from primordials and spoofable through a user-defined .constructor to boot. - The buffered fast paths in ReadableStreamDefaultReader.read() and the async iterator only covered default controllers, so byte streams with queued data still allocated a read request and PromiseWithResolvers per chunk. Byte-queue dequeue is fully synchronous (it is the queue-filled arm of the byte controller's pull steps), so both fast paths now resolve directly from the byte queue. - readableByteStreamControllerEnqueue re-ran the reader brand check and re-loaded the read request list four times per chunk across HasDefaultReader / ProcessReadRequestsUsingQueue / GetNumReadRequests / FulfillReadRequest; it now does a single pass. The async iterator also reuses its read request object across reads (at most one is ever in flight). benchmark/webstreams interleaved same-day A/B, --runs 10: readable-async-iterator bytes +16.3% (***), readable-read byob +9.1% (***), all other rows neutral. Profiler harness: parked byte iteration +14%, buffered byte iteration +37%, buffered byte read loop +18%, default-stream rows at parity. WPT streams/compression/encoding subtests identical to baseline. Signed-off-by: Matteo Collina <hello@matteocollina.com>
Signed-off-by: Matteo Collina <hello@matteocollina.com>
2782884 to
fa8ad29
Compare
Qard
approved these changes
Jul 5, 2026
Collaborator
|
CI: https://ci.nodejs.org/job/node-test-pull-request/74561/ Results |
aduh95
approved these changes
Jul 5, 2026
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.
for await/reader.read()loops over byte streams were ~4x slower than over default streams:ReflectGet(view.constructor.prototype, ...)-based ArrayBufferView getters with primordial getters (~3.5x faster at the call level, and no longer spoofable via a user-defined.constructor)ReadableStreamDefaultReader.read()and the async iterator to byte controllers, skipping the per-chunk read request +PromiseWithResolverswhen data is queuedbenchmark/webstreams(--runs 10): readable-async-iteratortype=bytes+16.3% (***), readable-readbyob+9.1% (***), all other rows neutral. WPT streams/compression/encoding results unchanged.