Skip to content

Commit fb750d6

Browse files
meixgbengl
authored andcommitted
perf_hooks: use arrays to store EntryBuffers
Also order entries by startTime when calling getEntriesByType. Fix: #42004 Fix: #42024 PR-URL: #42032 Fixes: #42004 Fixes: #42024 Reviewed-By: Benjamin Gruenbaum <[email protected]> Reviewed-By: Antoine du Hamel <[email protected]>
1 parent 48fa1e5 commit fb750d6

File tree

3 files changed

+59
-74
lines changed

3 files changed

+59
-74
lines changed

lib/internal/perf/observe.js

+24-71
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ const {
44
ArrayFrom,
55
ArrayIsArray,
66
ArrayPrototypeFilter,
7-
ArrayPrototypeFlatMap,
87
ArrayPrototypeIncludes,
98
ArrayPrototypePush,
109
ArrayPrototypePushApply,
1110
ArrayPrototypeSlice,
1211
ArrayPrototypeSort,
12+
ArrayPrototypeConcat,
1313
Error,
1414
ObjectDefineProperties,
1515
ObjectFreeze,
@@ -34,7 +34,6 @@ const {
3434
const {
3535
InternalPerformanceEntry,
3636
isPerformanceEntry,
37-
kBufferNext,
3837
} = require('internal/perf/performance_entry');
3938

4039
const {
@@ -89,8 +88,8 @@ const kSupportedEntryTypes = ObjectFreeze([
8988
]);
9089

9190
// Performance timeline entry Buffers
92-
const markEntryBuffer = createBuffer();
93-
const measureEntryBuffer = createBuffer();
91+
let markEntryBuffer = [];
92+
let measureEntryBuffer = [];
9493
const kMaxPerformanceEntryBuffers = 1e6;
9594
const kClearPerformanceEntryBuffers = ObjectFreeze({
9695
'mark': 'performance.clearMarks',
@@ -154,9 +153,7 @@ function maybeIncrementObserverCount(type) {
154153
class PerformanceObserverEntryList {
155154
constructor(entries) {
156155
this[kBuffer] = ArrayPrototypeSort(entries, (first, second) => {
157-
if (first.startTime < second.startTime) return -1;
158-
if (first.startTime > second.startTime) return 1;
159-
return 0;
156+
return first.startTime - second.startTime;
160157
});
161158
}
162159

@@ -344,15 +341,8 @@ function enqueue(entry) {
344341
return;
345342
}
346343

347-
const count = buffer.count + 1;
348-
buffer.count = count;
349-
if (count === 1) {
350-
buffer.head = entry;
351-
buffer.tail = entry;
352-
return;
353-
}
354-
buffer.tail[kBufferNext] = entry;
355-
buffer.tail = entry;
344+
ArrayPrototypePush(buffer, entry);
345+
const count = buffer.length;
356346

357347
if (count > kMaxPerformanceEntryBuffers &&
358348
!kWarnedEntryTypes.has(entryType)) {
@@ -372,63 +362,40 @@ function enqueue(entry) {
372362
}
373363

374364
function clearEntriesFromBuffer(type, name) {
375-
let buffer;
376-
if (type === 'mark') {
377-
buffer = markEntryBuffer;
378-
} else if (type === 'measure') {
379-
buffer = measureEntryBuffer;
380-
} else {
381-
return;
382-
}
383-
if (name === undefined) {
384-
resetBuffer(buffer);
365+
if (type !== 'mark' && type !== 'measure') {
385366
return;
386367
}
387368

388-
let head = null;
389-
let tail = null;
390-
let count = 0;
391-
for (let entry = buffer.head; entry !== null; entry = entry[kBufferNext]) {
392-
if (entry.name !== name) {
393-
head = head ?? entry;
394-
tail = entry;
395-
continue;
396-
}
397-
if (tail === null) {
398-
continue;
399-
}
400-
tail[kBufferNext] = entry[kBufferNext];
401-
count++;
369+
if (type === 'mark') {
370+
markEntryBuffer = name === undefined ?
371+
[] : ArrayPrototypeFilter(markEntryBuffer, (entry) => entry.name !== name);
372+
} else {
373+
measureEntryBuffer = name === undefined ?
374+
[] : ArrayPrototypeFilter(measureEntryBuffer, (entry) => entry.name !== name);
402375
}
403-
buffer.head = head;
404-
buffer.tail = tail;
405-
buffer.count = count;
406376
}
407377

408378
function filterBufferMapByNameAndType(name, type) {
409379
let bufferList;
410380
if (type === 'mark') {
411-
bufferList = [markEntryBuffer];
381+
bufferList = markEntryBuffer;
412382
} else if (type === 'measure') {
413-
bufferList = [measureEntryBuffer];
383+
bufferList = measureEntryBuffer;
414384
} else if (type !== undefined) {
415385
// Unrecognized type;
416386
return [];
417387
} else {
418-
bufferList = [markEntryBuffer, measureEntryBuffer];
388+
bufferList = ArrayPrototypeConcat(markEntryBuffer, measureEntryBuffer);
419389
}
420-
return ArrayPrototypeFlatMap(bufferList,
421-
(buffer) => filterBufferByName(buffer, name));
422-
}
423-
424-
function filterBufferByName(buffer, name) {
425-
const arr = [];
426-
for (let entry = buffer.head; entry !== null; entry = entry[kBufferNext]) {
427-
if (name === undefined || entry.name === name) {
428-
ArrayPrototypePush(arr, entry);
429-
}
390+
if (name !== undefined) {
391+
bufferList = ArrayPrototypeFilter(bufferList, (buffer) => buffer.name === name);
392+
} else if (type !== undefined) {
393+
bufferList = ArrayPrototypeSlice(bufferList);
430394
}
431-
return arr;
395+
396+
return ArrayPrototypeSort(bufferList, (first, second) => {
397+
return first.startTime - second.startTime;
398+
});
432399
}
433400

434401
function observerCallback(name, type, startTime, duration, details) {
@@ -476,20 +443,6 @@ function hasObserver(type) {
476443
return observerCounts[observerType] > 0;
477444
}
478445

479-
function createBuffer() {
480-
return {
481-
head: null,
482-
tail: null,
483-
count: 0,
484-
};
485-
}
486-
487-
function resetBuffer(buffer) {
488-
buffer.head = null;
489-
buffer.tail = null;
490-
buffer.count = 0;
491-
}
492-
493446
module.exports = {
494447
PerformanceObserver,
495448
PerformanceObserverEntryList,

lib/internal/perf/performance_entry.js

-3
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ const kType = Symbol('kType');
2222
const kStart = Symbol('kStart');
2323
const kDuration = Symbol('kDuration');
2424
const kDetail = Symbol('kDetail');
25-
const kBufferNext = Symbol('kBufferNext');
2625

2726
function isPerformanceEntry(obj) {
2827
return obj?.[kName] !== undefined;
@@ -72,7 +71,6 @@ class InternalPerformanceEntry {
7271
this[kStart] = start;
7372
this[kDuration] = duration;
7473
this[kDetail] = detail;
75-
this[kBufferNext] = null;
7674
}
7775
}
7876

@@ -85,5 +83,4 @@ module.exports = {
8583
InternalPerformanceEntry,
8684
PerformanceEntry,
8785
isPerformanceEntry,
88-
kBufferNext,
8986
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// This file may needs to be updated to wpt:
2+
// https://github.com/web-platform-tests/wpt
3+
4+
import '../common/index.mjs';
5+
import assert from 'assert';
6+
7+
import { performance } from 'perf_hooks';
8+
import { setTimeout } from 'timers/promises';
9+
10+
// Order by startTime
11+
performance.mark('one');
12+
await setTimeout(50);
13+
performance.mark('two');
14+
await setTimeout(50);
15+
performance.mark('three');
16+
await setTimeout(50);
17+
performance.measure('three', 'three');
18+
await setTimeout(50);
19+
performance.measure('two', 'two');
20+
await setTimeout(50);
21+
performance.measure('one', 'one');
22+
const entries = performance.getEntriesByType('measure');
23+
assert.deepStrictEqual(entries.map((x) => x.name), ['one', 'two', 'three']);
24+
const allEntries = performance.getEntries();
25+
assert.deepStrictEqual(allEntries.map((x) => x.name), ['one', 'one', 'two', 'two', 'three', 'three']);
26+
27+
performance.mark('a');
28+
await setTimeout(50);
29+
performance.measure('a', 'a');
30+
await setTimeout(50);
31+
performance.mark('a');
32+
await setTimeout(50);
33+
performance.measure('a', 'one');
34+
const entriesByName = performance.getEntriesByName('a');
35+
assert.deepStrictEqual(entriesByName.map((x) => x.entryType), ['measure', 'mark', 'measure', 'mark']);

0 commit comments

Comments
 (0)