11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst { mustCall, mustCallAtLeast } = require('../common');
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ciconst assert = require('assert');
61cb0ef41Sopenharmony_ciconst {
71cb0ef41Sopenharmony_ci  Worker,
81cb0ef41Sopenharmony_ci  MessageChannel,
91cb0ef41Sopenharmony_ci  MessagePort,
101cb0ef41Sopenharmony_ci  parentPort,
111cb0ef41Sopenharmony_ci} = require('worker_threads');
121cb0ef41Sopenharmony_ciconst { eventLoopUtilization, now } = require('perf_hooks').performance;
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_ci// Use argv to detect whether we're running as a Worker called by this test vs.
151cb0ef41Sopenharmony_ci// this test also being called as a Worker.
161cb0ef41Sopenharmony_ciif (process.argv[2] === 'iamalive') {
171cb0ef41Sopenharmony_ci  const iaElu = idleActive(eventLoopUtilization());
181cb0ef41Sopenharmony_ci  // Checks that the worker bootstrap is running after the event loop started.
191cb0ef41Sopenharmony_ci  assert.ok(iaElu > 0, `${iaElu} <= 0`);
201cb0ef41Sopenharmony_ci  parentPort.once('message', mustCall((msg) => {
211cb0ef41Sopenharmony_ci    assert.ok(msg.metricsCh instanceof MessagePort);
221cb0ef41Sopenharmony_ci    msg.metricsCh.on('message', mustCallAtLeast(workerOnMetricsMsg, 1));
231cb0ef41Sopenharmony_ci  }));
241cb0ef41Sopenharmony_ci  return;
251cb0ef41Sopenharmony_ci}
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_cifunction workerOnMetricsMsg(msg) {
281cb0ef41Sopenharmony_ci  if (msg.cmd === 'close') {
291cb0ef41Sopenharmony_ci    return this.close();
301cb0ef41Sopenharmony_ci  }
311cb0ef41Sopenharmony_ci
321cb0ef41Sopenharmony_ci  if (msg.cmd === 'elu') {
331cb0ef41Sopenharmony_ci    return this.postMessage(eventLoopUtilization());
341cb0ef41Sopenharmony_ci  }
351cb0ef41Sopenharmony_ci
361cb0ef41Sopenharmony_ci  if (msg.cmd === 'spin') {
371cb0ef41Sopenharmony_ci    const elu = eventLoopUtilization();
381cb0ef41Sopenharmony_ci    const t = now();
391cb0ef41Sopenharmony_ci    while (now() - t < msg.dur);
401cb0ef41Sopenharmony_ci    return this.postMessage(eventLoopUtilization(elu));
411cb0ef41Sopenharmony_ci  }
421cb0ef41Sopenharmony_ci}
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_cilet worker;
451cb0ef41Sopenharmony_cilet metricsCh;
461cb0ef41Sopenharmony_cilet mainElu;
471cb0ef41Sopenharmony_cilet workerELU;
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_ci(function r() {
501cb0ef41Sopenharmony_ci  // Force some idle time to accumulate before proceeding with test.
511cb0ef41Sopenharmony_ci  if (eventLoopUtilization().idle <= 0)
521cb0ef41Sopenharmony_ci    return setTimeout(mustCall(r), 5);
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ci  mainElu = eventLoopUtilization();
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_ci  worker = new Worker(__filename, { argv: [ 'iamalive' ] });
571cb0ef41Sopenharmony_ci  metricsCh = new MessageChannel();
581cb0ef41Sopenharmony_ci  worker.postMessage({ metricsCh: metricsCh.port1 }, [ metricsCh.port1 ]);
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ci  workerELU = worker.performance.eventLoopUtilization;
611cb0ef41Sopenharmony_ci  metricsCh.port2.once('message', mustCall(checkWorkerIdle));
621cb0ef41Sopenharmony_ci  metricsCh.port2.postMessage({ cmd: 'elu' });
631cb0ef41Sopenharmony_ci  // Make sure it's still safe to call eventLoopUtilization() after the worker
641cb0ef41Sopenharmony_ci  // hass been closed.
651cb0ef41Sopenharmony_ci  worker.on('exit', mustCall(() => {
661cb0ef41Sopenharmony_ci    assert.deepStrictEqual(worker.performance.eventLoopUtilization(),
671cb0ef41Sopenharmony_ci                           { idle: 0, active: 0, utilization: 0 });
681cb0ef41Sopenharmony_ci  }));
691cb0ef41Sopenharmony_ci})();
701cb0ef41Sopenharmony_ci
711cb0ef41Sopenharmony_cifunction checkWorkerIdle(wElu) {
721cb0ef41Sopenharmony_ci  const perfWorkerElu = workerELU();
731cb0ef41Sopenharmony_ci  const tmpMainElu = eventLoopUtilization(mainElu);
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_ci  assert.ok(idleActive(wElu) > 0, `${idleActive(wElu)} <= 0`);
761cb0ef41Sopenharmony_ci  assert.ok(idleActive(workerELU(wElu)) > 0,
771cb0ef41Sopenharmony_ci            `${idleActive(workerELU(wElu))} <= 0`);
781cb0ef41Sopenharmony_ci  assert.ok(idleActive(perfWorkerElu) > idleActive(wElu),
791cb0ef41Sopenharmony_ci            `${idleActive(perfWorkerElu)} <= ${idleActive(wElu)}`);
801cb0ef41Sopenharmony_ci  assert.ok(idleActive(tmpMainElu) > idleActive(perfWorkerElu),
811cb0ef41Sopenharmony_ci            `${idleActive(tmpMainElu)} <= ${idleActive(perfWorkerElu)}`);
821cb0ef41Sopenharmony_ci
831cb0ef41Sopenharmony_ci  wElu = workerELU();
841cb0ef41Sopenharmony_ci  setTimeout(mustCall(() => {
851cb0ef41Sopenharmony_ci    wElu = workerELU(wElu);
861cb0ef41Sopenharmony_ci    // Some clocks fire early. Removing a few milliseconds to cover that.
871cb0ef41Sopenharmony_ci    assert.ok(idleActive(wElu) >= 45, `${idleActive(wElu)} < 45`);
881cb0ef41Sopenharmony_ci    // Cutting the idle time in half since it's possible that the call took a
891cb0ef41Sopenharmony_ci    // lot of resources to process?
901cb0ef41Sopenharmony_ci    assert.ok(wElu.idle >= 25, `${wElu.idle} < 25`);
911cb0ef41Sopenharmony_ci
921cb0ef41Sopenharmony_ci    checkWorkerActive();
931cb0ef41Sopenharmony_ci  }), 50);
941cb0ef41Sopenharmony_ci}
951cb0ef41Sopenharmony_ci
961cb0ef41Sopenharmony_cifunction checkWorkerActive() {
971cb0ef41Sopenharmony_ci  const w = workerELU();
981cb0ef41Sopenharmony_ci
991cb0ef41Sopenharmony_ci  metricsCh.port2.postMessage({ cmd: 'spin', dur: 50 });
1001cb0ef41Sopenharmony_ci  metricsCh.port2.once('message', (wElu) => {
1011cb0ef41Sopenharmony_ci    const w2 = workerELU(w);
1021cb0ef41Sopenharmony_ci
1031cb0ef41Sopenharmony_ci    assert.ok(w2.active >= 50, `${w2.active} < 50`);
1041cb0ef41Sopenharmony_ci    assert.ok(wElu.active >= 50, `${wElu.active} < 50`);
1051cb0ef41Sopenharmony_ci    assert.ok(idleActive(wElu) < idleActive(w2),
1061cb0ef41Sopenharmony_ci              `${idleActive(wElu)} >= ${idleActive(w2)}`);
1071cb0ef41Sopenharmony_ci
1081cb0ef41Sopenharmony_ci    metricsCh.port2.postMessage({ cmd: 'close' });
1091cb0ef41Sopenharmony_ci  });
1101cb0ef41Sopenharmony_ci}
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_cifunction idleActive(elu) {
1131cb0ef41Sopenharmony_ci  return elu.idle + elu.active;
1141cb0ef41Sopenharmony_ci}
115