• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2
3const { mustCall } = require('../common');
4
5const TIMEOUT = 10;
6const SPIN_DUR = 50;
7
8const assert = require('assert');
9const { performance } = require('perf_hooks');
10const { Worker, parentPort } = require('worker_threads');
11
12const { nodeTiming, eventLoopUtilization } = performance;
13const elu = eventLoopUtilization();
14
15// Take into account whether this test was started as a Worker.
16if (nodeTiming.loopStart === -1) {
17  assert.strictEqual(nodeTiming.idleTime, 0);
18  assert.deepStrictEqual(elu, { idle: 0, active: 0, utilization: 0 });
19  assert.deepStrictEqual(eventLoopUtilization(elu),
20                         { idle: 0, active: 0, utilization: 0 });
21  assert.deepStrictEqual(eventLoopUtilization(elu, eventLoopUtilization()),
22                         { idle: 0, active: 0, utilization: 0 });
23}
24
25const nodeTimingProps = ['name', 'entryType', 'startTime', 'duration',
26                         'nodeStart', 'v8Start', 'environment', 'loopStart',
27                         'loopExit', 'bootstrapComplete', 'idleTime'];
28for (const p of nodeTimingProps)
29  assert.ok(typeof JSON.parse(JSON.stringify(nodeTiming))[p] ===
30    typeof nodeTiming[p]);
31
32setTimeout(mustCall(function r() {
33  const elu1 = eventLoopUtilization();
34
35  // Force idle time to accumulate before allowing test to continue.
36  if (elu1.idle <= 0)
37    return setTimeout(mustCall(r), 5);
38
39  const t = Date.now();
40  while (Date.now() - t < SPIN_DUR) { }
41
42  const elu2 = eventLoopUtilization(elu1);
43  const elu3 = eventLoopUtilization();
44  const elu4 = eventLoopUtilization(elu3, elu1);
45
46  assert.strictEqual(elu2.idle, 0);
47  assert.strictEqual(elu4.idle, 0);
48  assert.strictEqual(elu2.utilization, 1);
49  assert.strictEqual(elu4.utilization, 1);
50  assert.strictEqual(elu3.active - elu1.active, elu4.active);
51  assert.ok(elu2.active > SPIN_DUR - 10, `${elu2.active} <= ${SPIN_DUR - 10}`);
52  assert.ok(elu2.active < elu4.active, `${elu2.active} >= ${elu4.active}`);
53  assert.ok(elu3.active > elu2.active, `${elu3.active} <= ${elu2.active}`);
54  assert.ok(elu3.active > elu4.active, `${elu3.active} <= ${elu4.active}`);
55
56  setTimeout(mustCall(runIdleTimeTest), TIMEOUT);
57}), 5);
58
59function runIdleTimeTest() {
60  const idleTime = nodeTiming.idleTime;
61  const elu1 = eventLoopUtilization();
62  const sum = elu1.idle + elu1.active;
63
64  assert.ok(sum >= elu1.idle && sum >= elu1.active,
65            `idle: ${elu1.idle}  active: ${elu1.active}  sum: ${sum}`);
66  assert.strictEqual(elu1.idle, idleTime);
67  assert.strictEqual(elu1.utilization, elu1.active / sum);
68
69  setTimeout(mustCall(runCalcTest), TIMEOUT, elu1);
70}
71
72function runCalcTest(elu1) {
73  const now = performance.now();
74  const elu2 = eventLoopUtilization();
75  const elu3 = eventLoopUtilization(elu2, elu1);
76  const active_delta = elu2.active - elu1.active;
77  const idle_delta = elu2.idle - elu1.idle;
78
79  assert.ok(elu2.idle >= 0, `${elu2.idle} < 0`);
80  assert.ok(elu2.active >= 0, `${elu2.active} < 0`);
81  assert.ok(elu3.idle >= 0, `${elu3.idle} < 0`);
82  assert.ok(elu3.active >= 0, `${elu3.active} < 0`);
83  assert.ok(elu2.idle + elu2.active > elu1.idle + elu1.active,
84            `${elu2.idle + elu2.active} <= ${elu1.idle + elu1.active}`);
85  assert.ok(elu2.idle + elu2.active >= now - nodeTiming.loopStart,
86            `${elu2.idle + elu2.active} < ${now - nodeTiming.loopStart}`);
87  assert.strictEqual(elu3.active, elu2.active - elu1.active);
88  assert.strictEqual(elu3.idle, elu2.idle - elu1.idle);
89  assert.strictEqual(elu3.utilization,
90                     active_delta / (idle_delta + active_delta));
91
92  setImmediate(mustCall(runWorkerTest));
93}
94
95function runWorkerTest() {
96  // Use argv to detect whether we're running as a Worker called by this test
97  // vs. this test also being called as a Worker.
98  if (process.argv[2] === 'iamalive') {
99    parentPort.postMessage(JSON.stringify(eventLoopUtilization()));
100    return;
101  }
102
103  const elu1 = eventLoopUtilization();
104  const worker = new Worker(__filename, { argv: [ 'iamalive' ] });
105
106  worker.on('message', mustCall((msg) => {
107    const elu2 = eventLoopUtilization(elu1);
108    const data = JSON.parse(msg);
109
110    assert.ok(elu2.active + elu2.idle > data.active + data.idle,
111              `${elu2.active + elu2.idle} <= ${data.active + data.idle}`);
112  }));
113}
114