perf_hooks: reducing overhead of performance observer entry list

PR-URL: https://github.com/nodejs/node/pull/50008
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
This commit is contained in:
Vinicius Lourenço
2023-10-03 21:38:32 -03:00
committed by GitHub
parent f7a160d5b4
commit 328bdac7f0
2 changed files with 64 additions and 16 deletions

View File

@@ -0,0 +1,49 @@
'use strict';
const assert = require('assert');
const common = require('../common.js');
const {
PerformanceObserver,
performance,
} = require('perf_hooks');
function randomFn() {
return Math.random();
}
const bench = common.createBenchmark(main, {
n: [1e5],
pending: [1, 10],
}, {
options: ['--expose-internals'],
});
let _result;
function fillQueue(timerfied, pending) {
for (let i = 0; i < pending; i++) {
_result = timerfied();
}
// Avoid V8 deadcode (elimination)
assert.ok(_result);
}
function main({ n, pending }) {
const timerfied = performance.timerify(randomFn);
let count = 0;
const obs = new PerformanceObserver((entries) => {
count += entries.getEntries().length;
if (count >= n) {
bench.end(count);
} else {
fillQueue(timerfied, pending);
}
});
obs.observe({ entryTypes: ['function'], buffered: true });
bench.start();
fillQueue(timerfied, pending);
}

View File

@@ -15,7 +15,6 @@ const {
ObjectDefineProperties,
ObjectFreeze,
ObjectKeys,
ReflectConstruct,
SafeMap,
SafeSet,
Symbol,
@@ -171,9 +170,18 @@ function maybeIncrementObserverCount(type) {
}
}
const kSkipThrow = Symbol('kSkipThrow');
const performanceObserverSorter = (first, second) => {
return first.startTime - second.startTime;
};
class PerformanceObserverEntryList {
constructor() {
throw new ERR_ILLEGAL_CONSTRUCTOR();
constructor(skipThrowSymbol = undefined, entries = []) {
if (skipThrowSymbol !== kSkipThrow) {
throw new ERR_ILLEGAL_CONSTRUCTOR();
}
this[kBuffer] = ArrayPrototypeSort(entries, performanceObserverSorter);
}
getEntries() {
@@ -232,14 +240,6 @@ ObjectDefineProperties(PerformanceObserverEntryList.prototype, {
},
});
function createPerformanceObserverEntryList(entries) {
return ReflectConstruct(function PerformanceObserverEntryList() {
this[kBuffer] = ArrayPrototypeSort(entries, (first, second) => {
return first.startTime - second.startTime;
});
}, [], PerformanceObserverEntryList);
}
class PerformanceObserver {
#buffer = [];
#entryTypes = new SafeSet();
@@ -349,8 +349,9 @@ class PerformanceObserver {
}
[kDispatch]() {
this.#callback(createPerformanceObserverEntryList(this.takeRecords()),
this);
const entryList = new PerformanceObserverEntryList(kSkipThrow, this.takeRecords());
this.#callback(entryList, this);
}
[kInspect](depth, options) {
@@ -523,9 +524,7 @@ function filterBufferMapByNameAndType(name, type) {
bufferList = ArrayPrototypeSlice(bufferList);
}
return ArrayPrototypeSort(bufferList, (first, second) => {
return first.startTime - second.startTime;
});
return ArrayPrototypeSort(bufferList, performanceObserverSorter);
}
function observerCallback(name, type, startTime, duration, details) {