11cb0ef41Sopenharmony_ci'use strict'; 21cb0ef41Sopenharmony_ci 31cb0ef41Sopenharmony_ciconst common = require('../common'); 41cb0ef41Sopenharmony_ciconst { performance } = require('perf_hooks'); 51cb0ef41Sopenharmony_ci// Get the start time as soon as possible. 61cb0ef41Sopenharmony_ciconst testStartTime = performance.now(); 71cb0ef41Sopenharmony_ciconst assert = require('assert'); 81cb0ef41Sopenharmony_ciconst { writeSync } = require('fs'); 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_ci// Use writeSync to stdout to avoid disturbing the loop. 111cb0ef41Sopenharmony_cifunction log(str) { 121cb0ef41Sopenharmony_ci writeSync(1, str + '\n'); 131cb0ef41Sopenharmony_ci} 141cb0ef41Sopenharmony_ci 151cb0ef41Sopenharmony_ciassert(performance); 161cb0ef41Sopenharmony_ciassert(performance.nodeTiming); 171cb0ef41Sopenharmony_ciassert.strictEqual(typeof performance.timeOrigin, 'number'); 181cb0ef41Sopenharmony_ci 191cb0ef41Sopenharmony_ciassert(testStartTime > 0, `${testStartTime} <= 0`); 201cb0ef41Sopenharmony_ci// Use a fairly large epsilon value, since we can only guarantee that the node 211cb0ef41Sopenharmony_ci// process started up in 15 seconds. 221cb0ef41Sopenharmony_ciassert(testStartTime < 15000, `${testStartTime} >= 15000`); 231cb0ef41Sopenharmony_ci 241cb0ef41Sopenharmony_ci// Use different ways to calculate process uptime to check that 251cb0ef41Sopenharmony_ci// performance.timeOrigin and performance.now() are in reasonable range. 261cb0ef41Sopenharmony_ciconst epsilon = 50; 271cb0ef41Sopenharmony_ci{ 281cb0ef41Sopenharmony_ci const uptime1 = Date.now() - performance.timeOrigin; 291cb0ef41Sopenharmony_ci const uptime2 = performance.now(); 301cb0ef41Sopenharmony_ci const uptime3 = process.uptime() * 1000; 311cb0ef41Sopenharmony_ci assert(Math.abs(uptime1 - uptime2) < epsilon, 321cb0ef41Sopenharmony_ci `Date.now() - performance.timeOrigin (${uptime1}) - ` + 331cb0ef41Sopenharmony_ci `performance.now() (${uptime2}) = ` + 341cb0ef41Sopenharmony_ci `${uptime1 - uptime2} >= +- ${epsilon}`); 351cb0ef41Sopenharmony_ci assert(Math.abs(uptime1 - uptime3) < epsilon, 361cb0ef41Sopenharmony_ci `Date.now() - performance.timeOrigin (${uptime1}) - ` + 371cb0ef41Sopenharmony_ci `process.uptime() * 1000 (${uptime3}) = ` + 381cb0ef41Sopenharmony_ci `${uptime1 - uptime3} >= +- ${epsilon}`); 391cb0ef41Sopenharmony_ci} 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_ciassert.strictEqual(performance.nodeTiming.name, 'node'); 421cb0ef41Sopenharmony_ciassert.strictEqual(performance.nodeTiming.entryType, 'node'); 431cb0ef41Sopenharmony_ci 441cb0ef41Sopenharmony_ci// Copy all the values from the getters. 451cb0ef41Sopenharmony_ciconst initialTiming = { ...performance.nodeTiming }; 461cb0ef41Sopenharmony_ci 471cb0ef41Sopenharmony_ci{ 481cb0ef41Sopenharmony_ci const { 491cb0ef41Sopenharmony_ci startTime, 501cb0ef41Sopenharmony_ci nodeStart, 511cb0ef41Sopenharmony_ci v8Start, 521cb0ef41Sopenharmony_ci environment, 531cb0ef41Sopenharmony_ci bootstrapComplete, 541cb0ef41Sopenharmony_ci } = initialTiming; 551cb0ef41Sopenharmony_ci 561cb0ef41Sopenharmony_ci assert.strictEqual(startTime, 0); 571cb0ef41Sopenharmony_ci assert.strictEqual(typeof nodeStart, 'number'); 581cb0ef41Sopenharmony_ci assert(nodeStart > 0, `nodeStart ${nodeStart} <= 0`); 591cb0ef41Sopenharmony_ci // The whole process starts before this test starts. 601cb0ef41Sopenharmony_ci assert(nodeStart < testStartTime, 611cb0ef41Sopenharmony_ci `nodeStart ${nodeStart} >= ${testStartTime}`); 621cb0ef41Sopenharmony_ci 631cb0ef41Sopenharmony_ci assert.strictEqual(typeof v8Start, 'number'); 641cb0ef41Sopenharmony_ci assert(v8Start > 0, `v8Start ${v8Start} <= 0`); 651cb0ef41Sopenharmony_ci // V8 starts after the process starts. 661cb0ef41Sopenharmony_ci assert(v8Start > nodeStart, `v8Start ${v8Start} <= ${nodeStart}`); 671cb0ef41Sopenharmony_ci // V8 starts before this test starts. 681cb0ef41Sopenharmony_ci assert(v8Start < testStartTime, 691cb0ef41Sopenharmony_ci `v8Start ${v8Start} >= ${testStartTime}`); 701cb0ef41Sopenharmony_ci 711cb0ef41Sopenharmony_ci assert.strictEqual(typeof environment, 'number'); 721cb0ef41Sopenharmony_ci assert(environment > 0, `environment ${environment} <= 0`); 731cb0ef41Sopenharmony_ci // Environment starts after V8 starts. 741cb0ef41Sopenharmony_ci assert(environment > v8Start, 751cb0ef41Sopenharmony_ci `environment ${environment} <= ${v8Start}`); 761cb0ef41Sopenharmony_ci // Environment starts before this test starts. 771cb0ef41Sopenharmony_ci assert(environment < testStartTime, 781cb0ef41Sopenharmony_ci `environment ${environment} >= ${testStartTime}`); 791cb0ef41Sopenharmony_ci 801cb0ef41Sopenharmony_ci assert.strictEqual(typeof bootstrapComplete, 'number'); 811cb0ef41Sopenharmony_ci assert(bootstrapComplete > 0, `bootstrapComplete ${bootstrapComplete} <= 0`); 821cb0ef41Sopenharmony_ci // Bootstrap completes after environment starts. 831cb0ef41Sopenharmony_ci assert(bootstrapComplete > environment, 841cb0ef41Sopenharmony_ci `bootstrapComplete ${bootstrapComplete} <= ${environment}`); 851cb0ef41Sopenharmony_ci // Bootstrap completes before this test starts. 861cb0ef41Sopenharmony_ci assert(bootstrapComplete < testStartTime, 871cb0ef41Sopenharmony_ci `bootstrapComplete ${bootstrapComplete} >= ${testStartTime}`); 881cb0ef41Sopenharmony_ci} 891cb0ef41Sopenharmony_ci 901cb0ef41Sopenharmony_cifunction checkNodeTiming(timing) { 911cb0ef41Sopenharmony_ci // Calculate the difference between now() and duration as soon as possible. 921cb0ef41Sopenharmony_ci const now = performance.now(); 931cb0ef41Sopenharmony_ci const delta = Math.abs(now - timing.duration); 941cb0ef41Sopenharmony_ci 951cb0ef41Sopenharmony_ci log(JSON.stringify(timing, null, 2)); 961cb0ef41Sopenharmony_ci // Check that the properties are still reasonable. 971cb0ef41Sopenharmony_ci assert.strictEqual(timing.name, 'node'); 981cb0ef41Sopenharmony_ci assert.strictEqual(timing.entryType, 'node'); 991cb0ef41Sopenharmony_ci 1001cb0ef41Sopenharmony_ci // Check that duration is positive and practically the same as 1011cb0ef41Sopenharmony_ci // performance.now() i.e. measures Node.js instance up time. 1021cb0ef41Sopenharmony_ci assert.strictEqual(typeof timing.duration, 'number'); 1031cb0ef41Sopenharmony_ci assert(timing.duration > 0, `timing.duration ${timing.duration} <= 0`); 1041cb0ef41Sopenharmony_ci assert(delta < 10, 1051cb0ef41Sopenharmony_ci `now (${now}) - timing.duration (${timing.duration}) = ${delta} >= 10`); 1061cb0ef41Sopenharmony_ci 1071cb0ef41Sopenharmony_ci // Check that the following fields do not change. 1081cb0ef41Sopenharmony_ci assert.strictEqual(timing.startTime, initialTiming.startTime); 1091cb0ef41Sopenharmony_ci assert.strictEqual(timing.nodeStart, initialTiming.nodeStart); 1101cb0ef41Sopenharmony_ci assert.strictEqual(timing.v8Start, initialTiming.v8Start); 1111cb0ef41Sopenharmony_ci assert.strictEqual(timing.environment, initialTiming.environment); 1121cb0ef41Sopenharmony_ci assert.strictEqual(timing.bootstrapComplete, initialTiming.bootstrapComplete); 1131cb0ef41Sopenharmony_ci 1141cb0ef41Sopenharmony_ci assert.strictEqual(typeof timing.loopStart, 'number'); 1151cb0ef41Sopenharmony_ci assert.strictEqual(typeof timing.loopExit, 'number'); 1161cb0ef41Sopenharmony_ci} 1171cb0ef41Sopenharmony_ci 1181cb0ef41Sopenharmony_cilog('check initial nodeTiming'); 1191cb0ef41Sopenharmony_cicheckNodeTiming(initialTiming); 1201cb0ef41Sopenharmony_ciassert.strictEqual(initialTiming.loopExit, -1); 1211cb0ef41Sopenharmony_ci 1221cb0ef41Sopenharmony_cifunction checkValue(timing, name, min, max) { 1231cb0ef41Sopenharmony_ci const value = timing[name]; 1241cb0ef41Sopenharmony_ci assert(value > 0, `${name} ${value} <= 0`); 1251cb0ef41Sopenharmony_ci // Loop starts after bootstrap completes. 1261cb0ef41Sopenharmony_ci assert(value > min, 1271cb0ef41Sopenharmony_ci `${name} ${value} <= ${min}`); 1281cb0ef41Sopenharmony_ci assert(value < max, `${name} ${value} >= ${max}`); 1291cb0ef41Sopenharmony_ci} 1301cb0ef41Sopenharmony_ci 1311cb0ef41Sopenharmony_cilet loopStart = initialTiming.loopStart; 1321cb0ef41Sopenharmony_ciif (common.isMainThread) { 1331cb0ef41Sopenharmony_ci // In the main thread, the loop does not start until we start an operation 1341cb0ef41Sopenharmony_ci // that requires it, e.g. setTimeout(). 1351cb0ef41Sopenharmony_ci assert.strictEqual(initialTiming.loopStart, -1); 1361cb0ef41Sopenharmony_ci log('Start timer'); 1371cb0ef41Sopenharmony_ci setTimeout(() => { 1381cb0ef41Sopenharmony_ci log('Check nodeTiming in timer'); 1391cb0ef41Sopenharmony_ci const timing = { ...performance.nodeTiming }; 1401cb0ef41Sopenharmony_ci checkNodeTiming(timing); 1411cb0ef41Sopenharmony_ci // Loop should start after we fire the timeout, and before we call 1421cb0ef41Sopenharmony_ci // performance.now() here. 1431cb0ef41Sopenharmony_ci loopStart = timing.loopStart; 1441cb0ef41Sopenharmony_ci checkValue(timing, 'loopStart', initialTiming.duration, performance.now()); 1451cb0ef41Sopenharmony_ci }, 1000); 1461cb0ef41Sopenharmony_ci} else { 1471cb0ef41Sopenharmony_ci // In the worker, the loop always starts before the user code is evaluated, 1481cb0ef41Sopenharmony_ci // and after bootstrap completes. 1491cb0ef41Sopenharmony_ci checkValue(initialTiming, 1501cb0ef41Sopenharmony_ci 'loopStart', 1511cb0ef41Sopenharmony_ci initialTiming.bootstrapComplete, 1521cb0ef41Sopenharmony_ci testStartTime); 1531cb0ef41Sopenharmony_ci} 1541cb0ef41Sopenharmony_ci 1551cb0ef41Sopenharmony_ciprocess.on('exit', () => { 1561cb0ef41Sopenharmony_ci log('Check nodeTiming in process exit event'); 1571cb0ef41Sopenharmony_ci const timing = { ...performance.nodeTiming }; 1581cb0ef41Sopenharmony_ci checkNodeTiming(timing); 1591cb0ef41Sopenharmony_ci // Check that loopStart does not change. 1601cb0ef41Sopenharmony_ci assert.strictEqual(timing.loopStart, loopStart); 1611cb0ef41Sopenharmony_ci checkValue(timing, 1621cb0ef41Sopenharmony_ci 'loopExit', 1631cb0ef41Sopenharmony_ci loopStart, 1641cb0ef41Sopenharmony_ci performance.now()); 1651cb0ef41Sopenharmony_ci}); 166