mirror of https://github.com/nodejs/node.git
168 lines
6.1 KiB
JavaScript
168 lines
6.1 KiB
JavaScript
'use strict';
|
|
|
|
const common = require('../common');
|
|
const { performance } = require('perf_hooks');
|
|
// Get the start time as soon as possible.
|
|
const testStartTime = performance.now();
|
|
const assert = require('assert');
|
|
const { writeSync } = require('fs');
|
|
|
|
// Use writeSync to stdout to avoid disturbing the loop.
|
|
function log(str) {
|
|
writeSync(1, str + '\n');
|
|
}
|
|
|
|
assert(performance);
|
|
assert(performance.nodeTiming);
|
|
assert.strictEqual(typeof performance.timeOrigin, 'number');
|
|
|
|
assert(testStartTime > 0, `${testStartTime} <= 0`);
|
|
// Use a fairly large epsilon value, since we can only guarantee that the node
|
|
// process started up in 15 seconds.
|
|
assert(testStartTime < 15000, `${testStartTime} >= 15000`);
|
|
|
|
// Use different ways to calculate process uptime to check that
|
|
// performance.timeOrigin and performance.now() are in reasonable range.
|
|
const epsilon = 50;
|
|
{
|
|
const uptime1 = Date.now() - performance.timeOrigin;
|
|
const uptime2 = performance.now();
|
|
const uptime3 = process.uptime() * 1000;
|
|
assert(Math.abs(uptime1 - uptime2) < epsilon,
|
|
`Date.now() - performance.timeOrigin (${uptime1}) - ` +
|
|
`performance.now() (${uptime2}) = ` +
|
|
`${uptime1 - uptime2} >= +- ${epsilon}`);
|
|
assert(Math.abs(uptime1 - uptime3) < epsilon,
|
|
`Date.now() - performance.timeOrigin (${uptime1}) - ` +
|
|
`process.uptime() * 1000 (${uptime3}) = ` +
|
|
`${uptime1 - uptime3} >= +- ${epsilon}`);
|
|
}
|
|
|
|
assert.strictEqual(performance.nodeTiming.name, 'node');
|
|
assert.strictEqual(performance.nodeTiming.entryType, 'node');
|
|
|
|
// If timing.duration gets copied into the argument instead of being computed
|
|
// via the getter, this should be called right after timing is created.
|
|
function checkNodeTiming(timing) {
|
|
// Calculate the difference between now() and duration as soon as possible.
|
|
const now = performance.now();
|
|
const delta = Math.abs(now - timing.duration);
|
|
|
|
log(JSON.stringify(timing, null, 2));
|
|
// Check that the properties are still reasonable.
|
|
assert.strictEqual(timing.name, 'node');
|
|
assert.strictEqual(timing.entryType, 'node');
|
|
|
|
// Check that duration is positive and practically the same as
|
|
// performance.now() i.e. measures Node.js instance up time.
|
|
assert.strictEqual(typeof timing.duration, 'number');
|
|
assert(timing.duration > 0, `timing.duration ${timing.duration} <= 0`);
|
|
assert(delta < 10,
|
|
`now (${now}) - timing.duration (${timing.duration}) = ${delta} >= ${10}`);
|
|
|
|
// Check that the following fields do not change.
|
|
assert.strictEqual(timing.startTime, initialTiming.startTime);
|
|
assert.strictEqual(timing.nodeStart, initialTiming.nodeStart);
|
|
assert.strictEqual(timing.v8Start, initialTiming.v8Start);
|
|
assert.strictEqual(timing.environment, initialTiming.environment);
|
|
assert.strictEqual(timing.bootstrapComplete, initialTiming.bootstrapComplete);
|
|
|
|
assert.strictEqual(typeof timing.loopStart, 'number');
|
|
assert.strictEqual(typeof timing.loopExit, 'number');
|
|
}
|
|
|
|
log('check initial nodeTiming');
|
|
// Copy all the values from the getters.
|
|
const initialTiming = { ...performance.nodeTiming };
|
|
checkNodeTiming(initialTiming);
|
|
|
|
{
|
|
const {
|
|
startTime,
|
|
nodeStart,
|
|
v8Start,
|
|
environment,
|
|
bootstrapComplete,
|
|
} = initialTiming;
|
|
|
|
assert.strictEqual(startTime, 0);
|
|
assert.strictEqual(typeof nodeStart, 'number');
|
|
assert(nodeStart > 0, `nodeStart ${nodeStart} <= 0`);
|
|
// The whole process starts before this test starts.
|
|
assert(nodeStart < testStartTime,
|
|
`nodeStart ${nodeStart} >= ${testStartTime}`);
|
|
|
|
assert.strictEqual(typeof v8Start, 'number');
|
|
assert(v8Start > 0, `v8Start ${v8Start} <= 0`);
|
|
// V8 starts after the process starts.
|
|
assert(v8Start > nodeStart, `v8Start ${v8Start} <= ${nodeStart}`);
|
|
// V8 starts before this test starts.
|
|
assert(v8Start < testStartTime,
|
|
`v8Start ${v8Start} >= ${testStartTime}`);
|
|
|
|
assert.strictEqual(typeof environment, 'number');
|
|
assert(environment > 0, `environment ${environment} <= 0`);
|
|
// Environment starts after V8 starts.
|
|
assert(environment > v8Start,
|
|
`environment ${environment} <= ${v8Start}`);
|
|
// Environment starts before this test starts.
|
|
assert(environment < testStartTime,
|
|
`environment ${environment} >= ${testStartTime}`);
|
|
|
|
assert.strictEqual(typeof bootstrapComplete, 'number');
|
|
assert(bootstrapComplete > 0, `bootstrapComplete ${bootstrapComplete} <= 0`);
|
|
// Bootstrap completes after environment starts.
|
|
assert(bootstrapComplete > environment,
|
|
`bootstrapComplete ${bootstrapComplete} <= ${environment}`);
|
|
// Bootstrap completes before this test starts.
|
|
assert(bootstrapComplete < testStartTime,
|
|
`bootstrapComplete ${bootstrapComplete} >= ${testStartTime}`);
|
|
}
|
|
|
|
assert.strictEqual(initialTiming.loopExit, -1);
|
|
|
|
function checkValue(timing, name, min, max) {
|
|
const value = timing[name];
|
|
assert(value > 0, `${name} ${value} <= 0`);
|
|
// Loop starts after bootstrap completes.
|
|
assert(value > min,
|
|
`${name} ${value} <= ${min}`);
|
|
assert(value < max, `${name} ${value} >= ${max}`);
|
|
}
|
|
|
|
let loopStart = initialTiming.loopStart;
|
|
if (common.isMainThread) {
|
|
// In the main thread, the loop does not start until we start an operation
|
|
// that requires it, e.g. setTimeout().
|
|
assert.strictEqual(initialTiming.loopStart, -1);
|
|
log('Start timer');
|
|
setTimeout(() => {
|
|
log('Check nodeTiming in timer');
|
|
const timing = { ...performance.nodeTiming };
|
|
checkNodeTiming(timing);
|
|
// Loop should start after we fire the timeout, and before we call
|
|
// performance.now() here.
|
|
loopStart = timing.loopStart;
|
|
checkValue(timing, 'loopStart', initialTiming.duration, performance.now());
|
|
}, 1000);
|
|
} else {
|
|
// In the worker, the loop always starts before the user code is evaluated,
|
|
// and after bootstrap completes.
|
|
checkValue(initialTiming,
|
|
'loopStart',
|
|
initialTiming.bootstrapComplete,
|
|
testStartTime);
|
|
}
|
|
|
|
process.on('exit', () => {
|
|
log('Check nodeTiming in process exit event');
|
|
const timing = { ...performance.nodeTiming };
|
|
checkNodeTiming(timing);
|
|
// Check that loopStart does not change.
|
|
assert.strictEqual(timing.loopStart, loopStart);
|
|
checkValue(timing,
|
|
'loopExit',
|
|
loopStart,
|
|
performance.now());
|
|
});
|