-
Notifications
You must be signed in to change notification settings - Fork 30.4k
/
Copy pathtest-worker-eventlooputil.js
116 lines (96 loc) Β· 3.61 KB
/
test-worker-eventlooputil.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
'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 t = now();
while (now() - t < msg.dur);
return this.postMessage(eventLoopUtilization());
}
}
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);
worker = new Worker(__filename, { argv: [ 'iamalive' ] });
metricsCh = new MessageChannel();
worker.postMessage({ metricsCh: metricsCh.port1 }, [ metricsCh.port1 ]);
workerELU = worker.performance.eventLoopUtilization;
mainElu = 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 tmpMainElu = eventLoopUtilization(mainElu);
const perfWorkerElu = workerELU();
const eluDiff = eventLoopUtilization(perfWorkerElu, mainElu);
assert.strictEqual(idleActive(eluDiff),
(perfWorkerElu.active - mainElu.active) +
(perfWorkerElu.idle - mainElu.idle));
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(idleActive(wElu) > idleActive(w2),
`${idleActive(wElu)} <= ${idleActive(w2)}`);
metricsCh.port2.postMessage({ cmd: 'close' });
});
}
function idleActive(elu) {
return elu.idle + elu.active;
}