test: refactor test-readline-async-iterators into a benchmark

PR-URL: https://github.com/nodejs/node/pull/49237
Fixes: https://github.com/nodejs/node/issues/49224
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
This commit is contained in:
Shubham Pandey 2023-09-23 13:47:14 +05:30 committed by GitHub
parent 914ad2f518
commit c0b4208fb9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 36 additions and 112 deletions

View File

@ -5,6 +5,7 @@ const { Readable } = require('stream');
const bench = common.createBenchmark(main, {
n: [1e1, 1e2, 1e3, 1e4, 1e5, 1e6],
type: ['old', 'new'],
});
const loremIpsum = `Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed
@ -21,6 +22,37 @@ Condimentum mattis pellentesque id nibh tortor id aliquet lectus proin.
Diam in arcu cursus euismod quis viverra nibh.
Rest of line`;
function oldWay() {
const readable = new Readable({
objectMode: true,
read: () => {
this.resume();
},
destroy: (err, cb) => {
this.off('line', lineListener);
this.off('close', closeListener);
this.close();
cb(err);
},
});
const lineListener = (input) => {
if (!readable.push(input)) {
// TODO(rexagod): drain to resume flow
this.pause();
}
};
const closeListener = () => {
readable.push(null);
};
const errorListener = (err) => {
readable.destroy(err);
};
this.on('error', errorListener);
this.on('line', lineListener);
this.on('close', closeListener);
return readable[Symbol.asyncIterator]();
}
function getLoremIpsumStream(repetitions) {
const readable = Readable({
objectMode: true,
@ -32,7 +64,7 @@ function getLoremIpsumStream(repetitions) {
return readable;
}
async function main({ n }) {
async function main({ n, type }) {
bench.start();
let lineCount = 0;
@ -40,8 +72,10 @@ async function main({ n }) {
input: getLoremIpsumStream(n),
});
const readlineIterable = type === 'old' ? oldWay.call(iterable) : iterable;
// eslint-disable-next-line no-unused-vars
for await (const _ of iterable) {
for await (const _ of readlineIterable) {
lineCount++;
}
bench.end(lineCount);

View File

@ -73,115 +73,6 @@ async function testMutual() {
}
}
async function testPerformance() {
const loremIpsum = `Lorem ipsum dolor sit amet, consectetur adipiscing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Dui accumsan sit amet nulla facilisi morbi tempus iaculis urna.
Eget dolor morbi non arcu risus quis varius quam quisque.
Lacus viverra vitae congue eu consequat ac felis donec.
Amet porttitor eget dolor morbi non arcu.
Velit ut tortor pretium viverra suspendisse.
Mauris nunc congue nisi vitae suscipit tellus.
Amet nisl suscipit adipiscing bibendum est ultricies integer.
Sit amet dictum sit amet justo donec enim diam.
Condimentum mattis pellentesque id nibh tortor id aliquet lectus proin.
Diam in arcu cursus euismod quis viverra nibh.
`;
const REPETITIONS = 10000;
const SAMPLE = 100;
const THRESHOLD = 81;
function getLoremIpsumStream() {
const readable = Readable({
objectMode: true,
});
let i = 0;
readable._read = () => readable.push(
i++ >= REPETITIONS ? null : loremIpsum
);
return readable;
}
function oldWay() {
const readable = new Readable({
objectMode: true,
read: () => {
this.resume();
},
destroy: (err, cb) => {
this.off('line', lineListener);
this.off('close', closeListener);
this.close();
cb(err);
},
});
const lineListener = (input) => {
if (!readable.push(input)) {
// TODO(rexagod): drain to resume flow
this.pause();
}
};
const closeListener = () => {
readable.push(null);
};
const errorListener = (err) => {
readable.destroy(err);
};
this.on('error', errorListener);
this.on('line', lineListener);
this.on('close', closeListener);
return readable[Symbol.asyncIterator]();
}
function getAvg(mean, x, n) {
return (mean * n + x) / (n + 1);
}
let totalTimeOldWay = 0;
let totalTimeNewWay = 0;
let totalCharsOldWay = 0;
let totalCharsNewWay = 0;
const linesOldWay = [];
const linesNewWay = [];
for (let time = 0; time < SAMPLE; time++) {
const rlOldWay = readline.createInterface({
input: getLoremIpsumStream(),
});
let currenttotalTimeOldWay = Date.now();
for await (const line of oldWay.call(rlOldWay)) {
totalCharsOldWay += line.length;
if (time === 0) {
linesOldWay.push(line);
}
}
currenttotalTimeOldWay = Date.now() - currenttotalTimeOldWay;
totalTimeOldWay = getAvg(totalTimeOldWay, currenttotalTimeOldWay, SAMPLE);
const rlNewWay = readline.createInterface({
input: getLoremIpsumStream(),
});
let currentTotalTimeNewWay = Date.now();
for await (const line of rlNewWay) {
totalCharsNewWay += line.length;
if (time === 0) {
linesNewWay.push(line);
}
}
currentTotalTimeNewWay = Date.now() - currentTotalTimeNewWay;
totalTimeNewWay = getAvg(totalTimeNewWay, currentTotalTimeNewWay, SAMPLE);
}
assert.strictEqual(totalCharsOldWay, totalCharsNewWay);
assert.strictEqual(linesOldWay.length, linesNewWay.length);
linesOldWay.forEach((line, index) =>
assert.strictEqual(line, linesNewWay[index])
);
const percentage = totalTimeNewWay * 100 / totalTimeOldWay;
assert.ok(percentage <= THRESHOLD, `Failed: ${totalTimeNewWay} isn't lesser than ${THRESHOLD}% of ${totalTimeOldWay}. Actual percentage: ${percentage.toFixed(2)}%`);
}
async function testSlowStreamForLeaks() {
const message = 'a\nb\nc\n';
const DELAY = 1;
@ -225,6 +116,5 @@ async function testSlowStreamForLeaks() {
testSimple()
.then(testMutual)
.then(testPerformance)
.then(testSlowStreamForLeaks)
.then(common.mustCall());