mirror of
https://github.com/nodejs/node.git
synced 2026-11-09 15:11:11 -05:00
Signed-off-by: James M Snell <jasnell@gmail.com> Assisted-By: Claude/Opus 4.6 PR-URL: https://github.com/nodejs/node/pull/62066 Reviewed-By: Robert Nagy <ronagy@icloud.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
105 lines
2.9 KiB
JavaScript
105 lines
2.9 KiB
JavaScript
// Throughput benchmark: gzip compress then decompress round-trip.
|
|
// Tests real-world compression performance across stream APIs.
|
|
'use strict';
|
|
|
|
const common = require('../common.js');
|
|
const { Readable, Writable, pipeline } = require('stream');
|
|
const zlib = require('zlib');
|
|
|
|
const bench = common.createBenchmark(main, {
|
|
api: ['classic', 'webstream', 'iter'],
|
|
datasize: [1024 * 1024, 16 * 1024 * 1024, 64 * 1024 * 1024],
|
|
n: [5],
|
|
}, {
|
|
flags: ['--experimental-stream-iter'],
|
|
});
|
|
|
|
const CHUNK_SIZE = 64 * 1024;
|
|
|
|
function main({ api, datasize, n }) {
|
|
const chunk = Buffer.alloc(CHUNK_SIZE, 'abcdefghij');
|
|
const totalOps = (datasize * n) / (1024 * 1024);
|
|
|
|
switch (api) {
|
|
case 'classic':
|
|
return benchClassic(chunk, datasize, n, totalOps);
|
|
case 'webstream':
|
|
return benchWebStream(chunk, datasize, n, totalOps);
|
|
case 'iter':
|
|
return benchIter(chunk, datasize, n, totalOps);
|
|
}
|
|
}
|
|
|
|
function benchClassic(chunk, datasize, n, totalOps) {
|
|
function run(cb) {
|
|
let remaining = datasize;
|
|
const r = new Readable({
|
|
read() {
|
|
if (remaining <= 0) { this.push(null); return; }
|
|
const size = Math.min(remaining, chunk.length);
|
|
remaining -= size;
|
|
this.push(size === chunk.length ? chunk : chunk.subarray(0, size));
|
|
},
|
|
});
|
|
const w = new Writable({ write(data, enc, cb) { cb(); } });
|
|
pipeline(r, zlib.createGzip(), zlib.createGunzip(), w, cb);
|
|
}
|
|
|
|
let i = 0;
|
|
bench.start();
|
|
(function next() {
|
|
if (i++ >= n) return bench.end(totalOps);
|
|
run(next);
|
|
})();
|
|
}
|
|
|
|
function benchWebStream(chunk, datasize, n, totalOps) {
|
|
async function run() {
|
|
let remaining = datasize;
|
|
const rs = new ReadableStream({
|
|
pull(controller) {
|
|
if (remaining <= 0) { controller.close(); return; }
|
|
const size = Math.min(remaining, chunk.length);
|
|
remaining -= size;
|
|
controller.enqueue(
|
|
size === chunk.length ? chunk : chunk.subarray(0, size));
|
|
},
|
|
});
|
|
const ws = new WritableStream({ write() {} });
|
|
await rs
|
|
.pipeThrough(new CompressionStream('gzip'))
|
|
.pipeThrough(new DecompressionStream('gzip'))
|
|
.pipeTo(ws);
|
|
}
|
|
|
|
(async () => {
|
|
bench.start();
|
|
for (let i = 0; i < n; i++) await run();
|
|
bench.end(totalOps);
|
|
})();
|
|
}
|
|
|
|
function benchIter(chunk, datasize, n, totalOps) {
|
|
const { pipeTo } = require('stream/iter');
|
|
const { compressGzip, decompressGzip } = require('zlib/iter');
|
|
|
|
async function run() {
|
|
let remaining = datasize;
|
|
async function* source() {
|
|
while (remaining > 0) {
|
|
const size = Math.min(remaining, chunk.length);
|
|
remaining -= size;
|
|
yield [size === chunk.length ? chunk : chunk.subarray(0, size)];
|
|
}
|
|
}
|
|
await pipeTo(source(), compressGzip(), decompressGzip(),
|
|
{ write() {}, writeSync() { return true; } });
|
|
}
|
|
|
|
(async () => {
|
|
bench.start();
|
|
for (let i = 0; i < n; i++) await run();
|
|
bench.end(totalOps);
|
|
})();
|
|
}
|