mirror of
https://github.com/nodejs/node.git
synced 2025-05-05 21:04:16 +00:00

The active worker check compared the time from sending message till response arrived from worker with the complete time the worker was running till it responses to the spin request. If sending back the message is slow for some reason the test fails. Adapt the test to compare the time seen inside the worker with the time read from main thread. PR-URL: https://github.com/nodejs/node/pull/35891 Fixes: https://github.com/nodejs/node/issues/35844 Refs: https://github.com/nodejs/node/pull/35886 Refs: https://github.com/nodejs/node/pull/35664 Reviewed-By: Gireesh Punathil <gpunathi@in.ibm.com> Reviewed-By: Rich Trott <rtrott@gmail.com>
115 lines
3.5 KiB
JavaScript
115 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 { eventLoopUtilization, now } = 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 = now();
|
|
while (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
|
|
// hass 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;
|
|
}
|