mirror of
https://github.com/nodejs/node.git
synced 2026-10-28 18:25:13 +08:00
ReadableStream.prototype.values() built each iterator from an object literal with a computed symbol-key method plus five closures. Such a literal is rebuilt through the runtime on every evaluation, costing close to a microsecond per iterator, which dominates iterating a short-lived stream. Move next() and return() to a shared ReadableStreamAsyncIterator prototype, as for any WebIDL async iterator, and keep the per-iterator state in its read request. The prototype chain and property shape are the ones WPT checks; the placeholder AsyncIterator object in util.js is no longer needed. As in WebIDL, next() and return() now reject when called on something that is not a ReadableStream async iterator, and iterators no longer carry own next/return properties. Add an async-iterator kind to benchmark/webstreams/lifecycle.js. webstreams/lifecycle.js kind='async-iterator' *** +16.22% Signed-off-by: Matteo Collina <hello@matteocollina.com> PR-URL: https://github.com/nodejs/node/pull/66392 Reviewed-By: Paolo Insogna <paolo@cowtech.it> Reviewed-By: René <contact.9a5d6388@renegade334.me.uk>
92 lines
1.9 KiB
JavaScript
92 lines
1.9 KiB
JavaScript
'use strict';
|
|
const common = require('../common.js');
|
|
const assert = require('assert');
|
|
const {
|
|
ReadableStream,
|
|
WritableStream,
|
|
TransformStream,
|
|
} = require('node:stream/web');
|
|
|
|
const bench = common.createBenchmark(main, {
|
|
n: [5e4],
|
|
kind: ['readable', 'async-iterator', 'pipe-to', 'pipe-through'],
|
|
});
|
|
|
|
const chunk = Buffer.alloc(1024);
|
|
|
|
function makeSource() {
|
|
let i = 0;
|
|
return {
|
|
pull(controller) {
|
|
if (i++ < 4)
|
|
controller.enqueue(chunk);
|
|
else
|
|
controller.close();
|
|
},
|
|
};
|
|
}
|
|
|
|
async function readable(n) {
|
|
let chunks = 0;
|
|
bench.start();
|
|
for (let i = 0; i < n; i++) {
|
|
const reader = new ReadableStream(makeSource()).getReader();
|
|
while (!(await reader.read()).done) chunks++;
|
|
}
|
|
bench.end(n);
|
|
assert.strictEqual(chunks, n * 4);
|
|
}
|
|
|
|
async function asyncIterator(n) {
|
|
let chunks = 0;
|
|
bench.start();
|
|
for (let i = 0; i < n; i++) {
|
|
for await (const chunk of new ReadableStream(makeSource())) {
|
|
if (chunk) chunks++;
|
|
}
|
|
}
|
|
bench.end(n);
|
|
assert.strictEqual(chunks, n * 4);
|
|
}
|
|
|
|
async function pipeTo(n) {
|
|
let chunks = 0;
|
|
bench.start();
|
|
for (let i = 0; i < n; i++) {
|
|
await new ReadableStream(makeSource())
|
|
.pipeTo(new WritableStream({ write() { chunks++; } }));
|
|
}
|
|
bench.end(n);
|
|
assert.strictEqual(chunks, n * 4);
|
|
}
|
|
|
|
async function pipeThrough(n) {
|
|
let chunks = 0;
|
|
bench.start();
|
|
for (let i = 0; i < n; i++) {
|
|
const reader = new ReadableStream(makeSource())
|
|
.pipeThrough(new TransformStream())
|
|
.getReader();
|
|
while (!(await reader.read()).done) chunks++;
|
|
}
|
|
bench.end(n);
|
|
assert.strictEqual(chunks, n * 4);
|
|
}
|
|
|
|
function main({ n, kind }) {
|
|
switch (kind) {
|
|
case 'readable':
|
|
readable(n);
|
|
break;
|
|
case 'async-iterator':
|
|
asyncIterator(n);
|
|
break;
|
|
case 'pipe-to':
|
|
pipeTo(n);
|
|
break;
|
|
case 'pipe-through':
|
|
pipeThrough(n);
|
|
break;
|
|
}
|
|
}
|