Skip to content

Commit a517be0

Browse files
H4adtargos
authored andcommitted
perf_hooks: reducing overhead of performance observer entry list
PR-URL: #50008 Reviewed-By: Stephen Belanger <[email protected]> Reviewed-By: Yagiz Nizipli <[email protected]>
1 parent d7132d9 commit a517be0

File tree

2 files changed

+64
-16
lines changed

2 files changed

+64
-16
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
'use strict';
2+
3+
const assert = require('assert');
4+
const common = require('../common.js');
5+
6+
const {
7+
PerformanceObserver,
8+
performance,
9+
} = require('perf_hooks');
10+
11+
function randomFn() {
12+
return Math.random();
13+
}
14+
15+
const bench = common.createBenchmark(main, {
16+
n: [1e5],
17+
pending: [1, 10],
18+
}, {
19+
options: ['--expose-internals'],
20+
});
21+
22+
let _result;
23+
24+
function fillQueue(timerfied, pending) {
25+
for (let i = 0; i < pending; i++) {
26+
_result = timerfied();
27+
}
28+
// Avoid V8 deadcode (elimination)
29+
assert.ok(_result);
30+
}
31+
32+
function main({ n, pending }) {
33+
const timerfied = performance.timerify(randomFn);
34+
35+
let count = 0;
36+
const obs = new PerformanceObserver((entries) => {
37+
count += entries.getEntries().length;
38+
39+
if (count >= n) {
40+
bench.end(count);
41+
} else {
42+
fillQueue(timerfied, pending);
43+
}
44+
});
45+
obs.observe({ entryTypes: ['function'], buffered: true });
46+
47+
bench.start();
48+
fillQueue(timerfied, pending);
49+
}

lib/internal/perf/observe.js

+15-16
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ const {
1515
ObjectDefineProperties,
1616
ObjectFreeze,
1717
ObjectKeys,
18-
ReflectConstruct,
1918
SafeMap,
2019
SafeSet,
2120
Symbol,
@@ -171,9 +170,18 @@ function maybeIncrementObserverCount(type) {
171170
}
172171
}
173172

173+
const kSkipThrow = Symbol('kSkipThrow');
174+
const performanceObserverSorter = (first, second) => {
175+
return first.startTime - second.startTime;
176+
};
177+
174178
class PerformanceObserverEntryList {
175-
constructor() {
176-
throw new ERR_ILLEGAL_CONSTRUCTOR();
179+
constructor(skipThrowSymbol = undefined, entries = []) {
180+
if (skipThrowSymbol !== kSkipThrow) {
181+
throw new ERR_ILLEGAL_CONSTRUCTOR();
182+
}
183+
184+
this[kBuffer] = ArrayPrototypeSort(entries, performanceObserverSorter);
177185
}
178186

179187
getEntries() {
@@ -232,14 +240,6 @@ ObjectDefineProperties(PerformanceObserverEntryList.prototype, {
232240
},
233241
});
234242

235-
function createPerformanceObserverEntryList(entries) {
236-
return ReflectConstruct(function PerformanceObserverEntryList() {
237-
this[kBuffer] = ArrayPrototypeSort(entries, (first, second) => {
238-
return first.startTime - second.startTime;
239-
});
240-
}, [], PerformanceObserverEntryList);
241-
}
242-
243243
class PerformanceObserver {
244244
#buffer = [];
245245
#entryTypes = new SafeSet();
@@ -349,8 +349,9 @@ class PerformanceObserver {
349349
}
350350

351351
[kDispatch]() {
352-
this.#callback(createPerformanceObserverEntryList(this.takeRecords()),
353-
this);
352+
const entryList = new PerformanceObserverEntryList(kSkipThrow, this.takeRecords());
353+
354+
this.#callback(entryList, this);
354355
}
355356

356357
[kInspect](depth, options) {
@@ -523,9 +524,7 @@ function filterBufferMapByNameAndType(name, type) {
523524
bufferList = ArrayPrototypeSlice(bufferList);
524525
}
525526

526-
return ArrayPrototypeSort(bufferList, (first, second) => {
527-
return first.startTime - second.startTime;
528-
});
527+
return ArrayPrototypeSort(bufferList, performanceObserverSorter);
529528
}
530529

531530
function observerCallback(name, type, startTime, duration, details) {

0 commit comments

Comments
 (0)