From c0b4208fb9918523210ea23b577b8426fc85e434 Mon Sep 17 00:00:00 2001 From: Shubham Pandey Date: Sat, 23 Sep 2023 13:47:14 +0530 Subject: [PATCH] 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 --- benchmark/readline/readline-iterable.js | 38 +++++- .../parallel/test-readline-async-iterators.js | 110 ------------------ 2 files changed, 36 insertions(+), 112 deletions(-) diff --git a/benchmark/readline/readline-iterable.js b/benchmark/readline/readline-iterable.js index e92e5d005ea..9be4ea1f52b 100644 --- a/benchmark/readline/readline-iterable.js +++ b/benchmark/readline/readline-iterable.js @@ -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); diff --git a/test/parallel/test-readline-async-iterators.js b/test/parallel/test-readline-async-iterators.js index fdd3edaaf9e..32fa32a1284 100644 --- a/test/parallel/test-readline-async-iterators.js +++ b/test/parallel/test-readline-async-iterators.js @@ -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());