node/test/sequential/test-worker-eventlooputil.js
Nathan Baulch 28c7394319
test: fix typos
PR-URL: https://github.com/nodejs/node/pull/55063
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
2024-09-28 13:58:55 +00:00

116 lines
3.5 KiB
JavaScript

'use strict';
const { mustCall, mustCallAtLeast } = require('../common');
const assert = require('assert');
const {
Worker,
MessageChannel,
MessagePort,
parentPort,
} = require('worker_threads');
const { performance } = require('perf_hooks');
const { eventLoopUtilization } = require('perf_hooks').performance;
// Use argv to detect whether we're running as a Worker called by this test vs.
// this test also being called as a Worker.
if (process.argv[2] === 'iamalive') {
const iaElu = idleActive(eventLoopUtilization());
// Checks that the worker bootstrap is running after the event loop started.
assert.ok(iaElu > 0, `${iaElu} <= 0`);
parentPort.once('message', mustCall((msg) => {
assert.ok(msg.metricsCh instanceof MessagePort);
msg.metricsCh.on('message', mustCallAtLeast(workerOnMetricsMsg, 1));
}));
return;
}
function workerOnMetricsMsg(msg) {
if (msg.cmd === 'close') {
return this.close();
}
if (msg.cmd === 'elu') {
return this.postMessage(eventLoopUtilization());
}
if (msg.cmd === 'spin') {
const elu = eventLoopUtilization();
const t = performance.now();
while (performance.now() - t < msg.dur);
return this.postMessage(eventLoopUtilization(elu));
}
}
let worker;
let metricsCh;
let mainElu;
let workerELU;
(function r() {
// Force some idle time to accumulate before proceeding with test.
if (eventLoopUtilization().idle <= 0)
return setTimeout(mustCall(r), 5);
mainElu = eventLoopUtilization();
worker = new Worker(__filename, { argv: [ 'iamalive' ] });
metricsCh = new MessageChannel();
worker.postMessage({ metricsCh: metricsCh.port1 }, [ metricsCh.port1 ]);
workerELU = worker.performance.eventLoopUtilization;
metricsCh.port2.once('message', mustCall(checkWorkerIdle));
metricsCh.port2.postMessage({ cmd: 'elu' });
// Make sure it's still safe to call eventLoopUtilization() after the worker
// has been closed.
worker.on('exit', mustCall(() => {
assert.deepStrictEqual(worker.performance.eventLoopUtilization(),
{ idle: 0, active: 0, utilization: 0 });
}));
})();
function checkWorkerIdle(wElu) {
const perfWorkerElu = workerELU();
const tmpMainElu = eventLoopUtilization(mainElu);
assert.ok(idleActive(wElu) > 0, `${idleActive(wElu)} <= 0`);
assert.ok(idleActive(workerELU(wElu)) > 0,
`${idleActive(workerELU(wElu))} <= 0`);
assert.ok(idleActive(perfWorkerElu) > idleActive(wElu),
`${idleActive(perfWorkerElu)} <= ${idleActive(wElu)}`);
assert.ok(idleActive(tmpMainElu) > idleActive(perfWorkerElu),
`${idleActive(tmpMainElu)} <= ${idleActive(perfWorkerElu)}`);
wElu = workerELU();
setTimeout(mustCall(() => {
wElu = workerELU(wElu);
// Some clocks fire early. Removing a few milliseconds to cover that.
assert.ok(idleActive(wElu) >= 45, `${idleActive(wElu)} < 45`);
// Cutting the idle time in half since it's possible that the call took a
// lot of resources to process?
assert.ok(wElu.idle >= 25, `${wElu.idle} < 25`);
checkWorkerActive();
}), 50);
}
function checkWorkerActive() {
const w = workerELU();
metricsCh.port2.postMessage({ cmd: 'spin', dur: 50 });
metricsCh.port2.once('message', (wElu) => {
const w2 = workerELU(w);
assert.ok(w2.active >= 50, `${w2.active} < 50`);
assert.ok(wElu.active >= 50, `${wElu.active} < 50`);
assert.ok(idleActive(wElu) < idleActive(w2),
`${idleActive(wElu)} >= ${idleActive(w2)}`);
metricsCh.port2.postMessage({ cmd: 'close' });
});
}
function idleActive(elu) {
return elu.idle + elu.active;
}