node/test/parallel/test-worker-eventlooputil.js
Gerhard Stoebich 9dbde1d4fc test: correct test-worker-eventlooputil
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>
2020-11-04 07:19:47 +00:00

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;
}