Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions benchmark/child_process/child-process-exec-maxbuffer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
'use strict';
const common = require('../common.js');
const { execFile } = require('child_process');

// Isolates stdout accumulation + maxBuffer handling in execFile(). The child
// writes `chunks` blocks of 64 KiB; the parent accumulates them through the
// native pipe read path and the JS buffering in lib/child_process.js until the
// process exits and the result buffer is handed to the callback.

const bench = common.createBenchmark(main, {
// Number of 64 KiB blocks written by the child: 1 MiB, 16 MiB, 64 MiB.
chunks: [16, 256, 1024],
n: [10],
});

function main({ n, chunks }) {
const script =
'const b = Buffer.alloc(65536, 0x61);' +
`for (let i = 0; i < ${chunks}; i++) process.stdout.write(b);`;
const args = ['-e', script];
const options = {
maxBuffer: chunks * 65536 + 65536,
encoding: 'buffer',
};

let left = n;
const run = () => {
execFile(process.execPath, args, options, (err) => {
if (err)
throw err;
if (--left === 0)
return bench.end(n);
run();
});
};

bench.start();
run();
}
47 changes: 47 additions & 0 deletions benchmark/child_process/child-process-ipc-roundtrip.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
'use strict';
if (process.argv[2] === 'child') {
// Echo every message straight back to the parent.
process.on('message', (msg) => {
process.send(msg);
});
} else {
const common = require('../common.js');
const bench = common.createBenchmark(main, {
len: [64, 256, 1024, 4096, 16384, 65536],
serialization: ['json', 'advanced'],
dur: [5],
});
const { spawn } = require('child_process');

function main({ dur, len, serialization }) {
const msg = { payload: '.'.repeat(len) };
const options = {
stdio: ['ignore', 'ignore', 'ignore', 'ipc'],
serialization,
};
const child = spawn(process.argv[0],
[process.argv[1], 'child'], options);

let messages = 0;
let finished = false;

child.on('message', () => {
messages++;
// Keep one round-trip in flight per completed one so both the serialize
// (write) and deserialize (read) paths stay saturated on both ends.
if (!finished)
child.send(msg);
});

bench.start();
// Prime a window of in-flight messages so the IPC channel never drains.
for (let i = 0; i < 256; i++)
child.send(msg);

setTimeout(() => {
finished = true;
bench.end(messages);
child.kill();
}, dur * 1000);
}
}
43 changes: 43 additions & 0 deletions benchmark/child_process/child-process-spawn-options.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
'use strict';
const common = require('../common.js');
const { spawn } = require('child_process');

// Isolates the cost of marshaling spawn() options across the JS -> C++ boundary
// (ProcessWrap::Spawn). A trivial, fast-exiting child is spawned repeatedly
// while scaling the number of environment pairs and arguments that have to be
// converted, so the per-spawn option-handling overhead is the dominant cost.

const isWindows = process.platform === 'win32';
const command = isWindows ? 'cmd' : 'true';
const baseArgs = isWindows ? ['/d', '/s', '/c', 'exit'] : [];

const bench = common.createBenchmark(main, {
n: [1000],
envc: [0, 64, 256, 1024],
argc: [0, 8, 64],
});

function main({ n, envc, argc }) {
const env = { ...process.env };
for (let i = 0; i < envc; i++)
env[`NODE_BENCH_VAR_${i}`] = `value_${i}`;

const args = baseArgs.slice();
for (let i = 0; i < argc; i++)
args.push(`arg_${i}`);

const options = { env, stdio: ['ignore', 'ignore', 'ignore'] };

let left = n;
const go = () => {
if (--left < 0)
return bench.end(n);
const child = spawn(command, args, options);
// The exit code is intentionally ignored: the child only exercises the
// option-marshaling path, it is not expected to do any useful work.
child.on('exit', go);
};

bench.start();
go();
}
Loading