mirror of
https://github.com/nodejs/node.git
synced 2025-05-04 23:42:17 +00:00

* Update the user timing implementation to conform to User Timing Level 3. * Reimplement user timing and timerify with pure JavaScript implementations * Simplify the C++ implementation for gc and http2 perf * Runtime deprecate additional perf entry properties in favor of the standard detail argument * Disable the `buffered` option on PerformanceObserver, all entries are queued and dispatched on setImmediate. Only entries with active observers are buffered. * This does remove the user timing and timerify trace events. Because the trace_events are still considered experimental, those can be removed without a deprecation cycle. They are removed to improve performance and reduce complexity. Old: `perf_hooks/usertiming.js n=100000: 92,378.01249733355` New: perf_hooks/usertiming.js n=100000: 270,393.5280638482` PR-URL: https://github.com/nodejs/node/pull/37136 Refs: https://github.com/nodejs/diagnostics/issues/464 Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Michaël Zasso <targos@protonmail.com>
181 lines
4.5 KiB
JavaScript
181 lines
4.5 KiB
JavaScript
'use strict';
|
|
|
|
const common = require('../common');
|
|
const assert = require('assert');
|
|
const {
|
|
PerformanceObserver,
|
|
PerformanceEntry,
|
|
PerformanceMark,
|
|
performance: {
|
|
nodeTiming,
|
|
mark,
|
|
measure,
|
|
clearMarks,
|
|
},
|
|
} = require('perf_hooks');
|
|
|
|
assert(PerformanceObserver);
|
|
assert(PerformanceEntry);
|
|
assert(PerformanceMark);
|
|
assert(mark);
|
|
assert(measure);
|
|
|
|
[undefined, 'a', 'null', 1, true].forEach((i) => {
|
|
const m = mark(i);
|
|
assert(m instanceof PerformanceEntry);
|
|
assert(m instanceof PerformanceMark);
|
|
|
|
assert.strictEqual(m.name, `${i}`);
|
|
assert.strictEqual(m.entryType, 'mark');
|
|
assert.strictEqual(typeof m.startTime, 'number');
|
|
assert.strictEqual(m.duration, 0);
|
|
assert.strictEqual(m.details, undefined);
|
|
});
|
|
|
|
clearMarks();
|
|
|
|
assert.throws(() => mark(Symbol('a')), {
|
|
message: /Cannot convert a Symbol value to a string/
|
|
});
|
|
|
|
[undefined, null, 1, 'any', {}, []].forEach((detail) => {
|
|
const m = mark('a', { detail });
|
|
assert.strictEqual(m.name, 'a');
|
|
assert.strictEqual(m.entryType, 'mark');
|
|
assert.strictEqual(m.detail, detail);
|
|
});
|
|
|
|
clearMarks();
|
|
|
|
{
|
|
const m = mark('a', { startTime: 1 });
|
|
assert.strictEqual(m.startTime, 1);
|
|
}
|
|
|
|
assert.throws(() => mark('a', { startTime: 'a' }), {
|
|
code: 'ERR_INVALID_ARG_TYPE'
|
|
});
|
|
|
|
clearMarks();
|
|
clearMarks(1);
|
|
clearMarks(null);
|
|
|
|
assert.throws(() => clearMarks(Symbol('foo')), {
|
|
message: /Cannot convert a Symbol value to a string/
|
|
});
|
|
|
|
{
|
|
mark('a', { startTime: 0 });
|
|
mark('b', { startTime: 10 });
|
|
|
|
{
|
|
const m3 = measure('foo', 'a', 'b');
|
|
assert.strictEqual(m3.name, 'foo');
|
|
assert.strictEqual(m3.entryType, 'measure');
|
|
assert.strictEqual(m3.startTime, 0);
|
|
assert.strictEqual(m3.duration, 10);
|
|
}
|
|
|
|
{
|
|
const m3 = measure('foo', 'a');
|
|
assert.strictEqual(m3.name, 'foo');
|
|
assert.strictEqual(m3.entryType, 'measure');
|
|
assert.strictEqual(m3.startTime, 0);
|
|
assert(m3.duration > 0); // Duration is non-deterministic here.
|
|
}
|
|
|
|
{
|
|
const m3 = measure('foo', { start: 'a' });
|
|
assert.strictEqual(m3.name, 'foo');
|
|
assert.strictEqual(m3.entryType, 'measure');
|
|
assert.strictEqual(m3.startTime, 0);
|
|
assert(m3.duration > 0); // Duration is non-deterministic here.
|
|
}
|
|
|
|
{
|
|
const m3 = measure('foo', { end: 'b' });
|
|
assert.strictEqual(m3.name, 'foo');
|
|
assert.strictEqual(m3.entryType, 'measure');
|
|
assert.strictEqual(m3.startTime, 0);
|
|
assert.strictEqual(m3.duration, 10);
|
|
}
|
|
|
|
{
|
|
const m3 = measure('foo', { duration: 11, end: 'b' });
|
|
assert.strictEqual(m3.name, 'foo');
|
|
assert.strictEqual(m3.entryType, 'measure');
|
|
assert.strictEqual(m3.startTime, -1);
|
|
assert.strictEqual(m3.duration, 11);
|
|
}
|
|
|
|
{
|
|
const m3 = measure('foo', { duration: 11, start: 'b' });
|
|
assert.strictEqual(m3.name, 'foo');
|
|
assert.strictEqual(m3.entryType, 'measure');
|
|
assert.strictEqual(m3.startTime, 10);
|
|
assert.strictEqual(m3.duration, 11);
|
|
}
|
|
|
|
{
|
|
const m3 = measure('foo', 'nodeStart');
|
|
assert.strictEqual(m3.name, 'foo');
|
|
assert.strictEqual(m3.entryType, 'measure');
|
|
assert.strictEqual(m3.startTime, nodeTiming.nodeStart);
|
|
assert(m3.duration > 0); // Duration is non-deterministic here.
|
|
}
|
|
|
|
{
|
|
const m3 = measure('foo', 'nodeStart', 'bootstrapComplete');
|
|
assert.strictEqual(m3.name, 'foo');
|
|
assert.strictEqual(m3.entryType, 'measure');
|
|
assert.strictEqual(m3.startTime, nodeTiming.nodeStart);
|
|
assert.strictEqual(
|
|
m3.duration,
|
|
nodeTiming.bootstrapComplete - nodeTiming.nodeStart);
|
|
}
|
|
|
|
{
|
|
const m3 = measure('foo', { start: 'nodeStart', duration: 10 });
|
|
assert.strictEqual(m3.name, 'foo');
|
|
assert.strictEqual(m3.entryType, 'measure');
|
|
assert.strictEqual(m3.startTime, nodeTiming.nodeStart);
|
|
assert.strictEqual(m3.duration, 10);
|
|
}
|
|
|
|
clearMarks();
|
|
}
|
|
|
|
{
|
|
const obs = new PerformanceObserver(common.mustCall((list) => {
|
|
{
|
|
const entries = list.getEntries();
|
|
assert.strictEqual(entries.length, 3);
|
|
}
|
|
{
|
|
const entries = list.getEntriesByType('mark');
|
|
assert.strictEqual(entries.length, 2);
|
|
}
|
|
{
|
|
const entries = list.getEntriesByType('measure');
|
|
assert.strictEqual(entries.length, 1);
|
|
}
|
|
{
|
|
const entries = list.getEntriesByName('a');
|
|
assert.strictEqual(entries.length, 1);
|
|
}
|
|
{
|
|
const entries = list.getEntriesByName('b');
|
|
assert.strictEqual(entries.length, 1);
|
|
}
|
|
{
|
|
const entries = list.getEntriesByName('a to b');
|
|
assert.strictEqual(entries.length, 1);
|
|
}
|
|
obs.disconnect();
|
|
}));
|
|
obs.observe({ entryTypes: ['mark', 'measure'] });
|
|
mark('a');
|
|
mark('b');
|
|
measure('a to b', 'a', 'b');
|
|
}
|