Skip to content

Commit 72b9e2f

Browse files
committed
perf_hooks: web performance timeline compliance
1 parent 4de6f20 commit 72b9e2f

File tree

88 files changed

+3779
-50
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

88 files changed

+3779
-50
lines changed

lib/internal/errors.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1226,8 +1226,6 @@ E('ERR_INVALID_PACKAGE_TARGET',
12261226
pkgPath}package.json${base ? ` imported from ${base}` : ''}${relError ?
12271227
'; targets must start with "./"' : ''}`;
12281228
}, Error);
1229-
E('ERR_INVALID_PERFORMANCE_MARK',
1230-
'The "%s" performance mark has not been set', Error);
12311229
E('ERR_INVALID_PROTOCOL',
12321230
'Protocol "%s" not supported. Expected "%s"',
12331231
TypeError);

lib/internal/perf/observe.js

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const {
44
ArrayFrom,
55
ArrayIsArray,
66
ArrayPrototypeFilter,
7+
ArrayPrototypeFlatMap,
78
ArrayPrototypeIncludes,
89
ArrayPrototypePush,
910
ArrayPrototypeSlice,
@@ -82,7 +83,12 @@ const kSupportedEntryTypes = ObjectFreeze([
8283
'mark',
8384
'measure',
8485
]);
86+
const kTimelineEntryTypes = ObjectFreeze([
87+
'mark',
88+
'measure',
89+
]);
8590

91+
const kPerformanceEntryBuffer = new SafeMap();
8692
const kObservers = new SafeSet();
8793
const kPending = new SafeSet();
8894
let isPending = false;
@@ -190,6 +196,7 @@ class PerformanceObserver {
190196
const {
191197
entryTypes,
192198
type,
199+
buffered,
193200
} = { ...options };
194201
if (entryTypes === undefined && type === undefined)
195202
throw new ERR_MISSING_ARGS('options.entryTypes', 'options.type');
@@ -229,6 +236,13 @@ class PerformanceObserver {
229236
return;
230237
this[kEntryTypes].add(type);
231238
maybeIncrementObserverCount(type);
239+
if (buffered) {
240+
const entries = filterBufferMapByNameAndType(undefined, type);
241+
this[kBuffer].push(...entries);
242+
kPending.add(this);
243+
if (kPending.size)
244+
queuePending();
245+
}
232246
}
233247

234248
if (this[kEntryTypes].size)
@@ -291,6 +305,52 @@ function enqueue(entry) {
291305
for (const obs of kObservers) {
292306
obs[kMaybeBuffer](entry);
293307
}
308+
309+
const entryType = entry.entryType;
310+
if (!kTimelineEntryTypes.includes(entryType)) {
311+
return;
312+
}
313+
const buffer = getEntryBuffer(entryType);
314+
buffer.push(entry);
315+
}
316+
317+
function clearEntriesFromBuffer(type, name) {
318+
if (name === undefined) {
319+
kPerformanceEntryBuffer.delete(type);
320+
return;
321+
}
322+
let buffer = getEntryBuffer(type);
323+
buffer = ArrayPrototypeFilter(
324+
buffer,
325+
(entry) => entry.name !== name);
326+
kPerformanceEntryBuffer.set(type, buffer);
327+
}
328+
329+
function getEntryBuffer(type) {
330+
let buffer = kPerformanceEntryBuffer.get(type);
331+
if (buffer === undefined) {
332+
buffer = [];
333+
kPerformanceEntryBuffer.set(type, buffer);
334+
}
335+
return buffer;
336+
}
337+
338+
function filterBufferMapByNameAndType(name, type) {
339+
let bufferList;
340+
if (type !== undefined) {
341+
bufferList = kPerformanceEntryBuffer.get(type) ?? [];
342+
} else {
343+
bufferList = ArrayFrom(kPerformanceEntryBuffer.values());
344+
}
345+
return ArrayPrototypeFlatMap(bufferList,
346+
(buffer) => filterBufferByName(buffer, name));
347+
}
348+
349+
function filterBufferByName(buffer, name) {
350+
if (name === undefined) {
351+
return buffer;
352+
}
353+
return ArrayPrototypeFilter(buffer, (it) => it.name === name);
294354
}
295355

296356
function observerCallback(name, type, startTime, duration, details) {
@@ -342,4 +402,6 @@ module.exports = {
342402
PerformanceObserver,
343403
enqueue,
344404
hasObserver,
405+
clearEntriesFromBuffer,
406+
filterBufferMapByNameAndType,
345407
};

lib/internal/perf/performance.js

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,12 @@ const { now } = require('internal/perf/utils');
1616
const {
1717
mark,
1818
measure,
19-
clearMarks,
19+
clearMarkTimings,
2020
} = require('internal/perf/usertiming');
21+
const {
22+
clearEntriesFromBuffer,
23+
filterBufferMapByNameAndType,
24+
} = require('internal/perf/observe');
2125

2226
const eventLoopUtilization = require('internal/perf/event_loop_utilization');
2327
const nodeTiming = require('internal/perf/nodetiming');
@@ -48,7 +52,6 @@ class Performance extends EventTarget {
4852
timeOrigin: this.timeOrigin,
4953
}, opts)}`;
5054
}
51-
5255
}
5356

5457
function toJSON() {
@@ -59,6 +62,39 @@ function toJSON() {
5962
};
6063
}
6164

65+
function clearMarks(name) {
66+
if (name !== undefined) {
67+
name = `${name}`;
68+
}
69+
clearMarkTimings(name);
70+
clearEntriesFromBuffer('mark', name);
71+
}
72+
73+
function clearMeasures(name) {
74+
if (name !== undefined) {
75+
name = `${name}`;
76+
}
77+
clearEntriesFromBuffer('measure', name);
78+
}
79+
80+
function getEntries() {
81+
return filterBufferMapByNameAndType();
82+
}
83+
84+
function getEntriesByName(name) {
85+
if (name !== undefined) {
86+
name = `${name}`;
87+
}
88+
return filterBufferMapByNameAndType(name, undefined);
89+
}
90+
91+
function getEntriesByType(type) {
92+
if (type !== undefined) {
93+
type = `${type}`;
94+
}
95+
return filterBufferMapByNameAndType(undefined, type);
96+
}
97+
6298
class InternalPerformance extends EventTarget {}
6399
InternalPerformance.prototype.constructor = Performance.prototype.constructor;
64100
ObjectSetPrototypeOf(InternalPerformance.prototype, Performance.prototype);
@@ -69,11 +105,31 @@ ObjectDefineProperties(Performance.prototype, {
69105
enumerable: false,
70106
value: clearMarks,
71107
},
108+
clearMeasures: {
109+
configurable: true,
110+
enumerable: false,
111+
value: clearMeasures,
112+
},
72113
eventLoopUtilization: {
73114
configurable: true,
74115
enumerable: false,
75116
value: eventLoopUtilization,
76117
},
118+
getEntries: {
119+
configurable: true,
120+
enumerable: false,
121+
value: getEntries,
122+
},
123+
getEntriesByName: {
124+
configurable: true,
125+
enumerable: false,
126+
value: getEntriesByName,
127+
},
128+
getEntriesByType: {
129+
configurable: true,
130+
enumerable: false,
131+
value: getEntriesByType,
132+
},
77133
mark: {
78134
configurable: true,
79135
enumerable: false,

0 commit comments

Comments
 (0)