mirror of https://github.com/nodejs/node.git
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:
parent
914ad2f518
commit
c0b4208fb9
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
|
|
Loading…
Reference in New Issue