mirror of
https://github.com/nodejs/node.git
synced 2025-05-02 17:01:08 +00:00

An initial implementation of the Performance Timing API for Node.js. This is the same Performance Timing API implemented by modern browsers with a number of Node.js specific properties. The User Timing mark() and measure() APIs are implemented, garbage collection timing, and node startup milestone timing. ```js const { performance } = require('perf_hooks'); performance.mark('A'); setTimeout(() => { performance.mark('B'); performance.measure('A to B', 'A', 'B'); const entry = performance.getEntriesByName('A to B', 'measure')[0]; console.log(entry.duration); }, 10000); ``` The implementation is at the native layer and makes use of uv_hrtime(). This should enable *eventual* integration with things like Tracing and Inspection. The implementation is extensible and should allow us to add new performance entry types as we go (e.g. for measuring i/o perf, etc). Documentation and a test are provided. PR-URL: https://github.com/nodejs/node/pull/14680 Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
94 lines
2.7 KiB
JavaScript
94 lines
2.7 KiB
JavaScript
'use strict';
|
|
|
|
const common = require('../common');
|
|
const assert = require('assert');
|
|
|
|
const {
|
|
performance,
|
|
PerformanceObserver
|
|
} = require('perf_hooks');
|
|
|
|
{
|
|
// Intentional non-op. Do not wrap in common.mustCall();
|
|
const n = performance.timerify(() => {});
|
|
n();
|
|
const entries = performance.getEntriesByType('function');
|
|
assert.strictEqual(entries.length, 0);
|
|
|
|
const obs = new PerformanceObserver(common.mustCall((list) => {
|
|
const entries = list.getEntries();
|
|
const entry = entries[0];
|
|
assert(entry);
|
|
assert.strictEqual(entry.name, 'performance.timerify');
|
|
assert.strictEqual(entry.entryType, 'function');
|
|
assert.strictEqual(typeof entry.duration, 'number');
|
|
assert.strictEqual(typeof entry.startTime, 'number');
|
|
obs.disconnect();
|
|
performance.clearFunctions();
|
|
}));
|
|
obs.observe({ entryTypes: ['function'] });
|
|
n();
|
|
}
|
|
|
|
{
|
|
// If the error throws, the error should just be bubbled up and the
|
|
// performance timeline entry will not be reported.
|
|
const obs = new PerformanceObserver(common.mustNotCall());
|
|
obs.observe({ entryTypes: ['function'] });
|
|
const n = performance.timerify(() => {
|
|
throw new Error('test');
|
|
});
|
|
assert.throws(() => n(), /^Error: test$/);
|
|
const entries = performance.getEntriesByType('function');
|
|
assert.strictEqual(entries.length, 0);
|
|
obs.disconnect();
|
|
}
|
|
|
|
{
|
|
class N {}
|
|
const n = performance.timerify(N);
|
|
new n();
|
|
const entries = performance.getEntriesByType('function');
|
|
assert.strictEqual(entries.length, 0);
|
|
|
|
const obs = new PerformanceObserver(common.mustCall((list) => {
|
|
const entries = list.getEntries();
|
|
const entry = entries[0];
|
|
assert.strictEqual(entry[0], 1);
|
|
assert.strictEqual(entry[1], 'abc');
|
|
assert(entry);
|
|
assert.strictEqual(entry.name, 'N');
|
|
assert.strictEqual(entry.entryType, 'function');
|
|
assert.strictEqual(typeof entry.duration, 'number');
|
|
assert.strictEqual(typeof entry.startTime, 'number');
|
|
obs.disconnect();
|
|
performance.clearFunctions();
|
|
}));
|
|
obs.observe({ entryTypes: ['function'] });
|
|
|
|
new n(1, 'abc');
|
|
}
|
|
|
|
{
|
|
[1, {}, [], null, undefined, Infinity].forEach((i) => {
|
|
assert.throws(() => performance.timerify(i),
|
|
common.expectsError({
|
|
code: 'ERR_INVALID_ARG_TYPE',
|
|
type: TypeError,
|
|
message: 'The "fn" argument must be of type Function'
|
|
}));
|
|
});
|
|
}
|
|
|
|
// Function can only be wrapped once, also check length and name
|
|
{
|
|
const m = (a, b = 1) => {};
|
|
const n = performance.timerify(m);
|
|
const o = performance.timerify(m);
|
|
const p = performance.timerify(n);
|
|
assert.strictEqual(n, o);
|
|
assert.strictEqual(n, p);
|
|
assert.strictEqual(n.length, m.length);
|
|
assert.strictEqual(n.name, 'timerified m');
|
|
}
|