Skip to content

Commit 5fd5fad

Browse files
committed
perf_hooks: reduce overhead of new user timings
1 parent aadfea4 commit 5fd5fad

File tree

2 files changed

+37
-29
lines changed

2 files changed

+37
-29
lines changed

lib/internal/perf/performance_entry.js

+4-9
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,10 @@ class PerformanceEntry {
4242
throw new ERR_ILLEGAL_CONSTRUCTOR();
4343
}
4444

45-
initPerformanceEntry(this, name, type, start, duration);
45+
this[kName] = name;
46+
this[kEntryType] = type;
47+
this[kStartTime] = start;
48+
this[kDuration] = duration;
4649
}
4750

4851
get name() {
@@ -94,13 +97,6 @@ ObjectDefineProperties(PerformanceEntry.prototype, {
9497
toJSON: kEnumerableProperty,
9598
});
9699

97-
function initPerformanceEntry(entry, name, type, start, duration) {
98-
entry[kName] = name;
99-
entry[kEntryType] = type;
100-
entry[kStartTime] = start;
101-
entry[kDuration] = duration;
102-
}
103-
104100
function createPerformanceEntry(name, type, start, duration) {
105101
return new PerformanceEntry(kSkipThrow, name, type, start, duration);
106102
}
@@ -135,7 +131,6 @@ function createPerformanceNodeEntry(name, type, start, duration, detail) {
135131
}
136132

137133
module.exports = {
138-
initPerformanceEntry,
139134
createPerformanceEntry,
140135
PerformanceEntry,
141136
isPerformanceEntry,

lib/internal/perf/usertiming.js

+33-20
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,14 @@
22

33
const {
44
ObjectDefineProperties,
5-
ObjectSetPrototypeOf,
65
SafeMap,
76
SafeSet,
87
SafeArrayIterator,
98
Symbol,
109
SymbolToStringTag,
11-
ReflectConstruct,
1210
} = primordials;
1311

14-
const { initPerformanceEntry, PerformanceEntry } = require('internal/perf/performance_entry');
12+
const { PerformanceEntry, kSkipThrow } = require('internal/perf/performance_entry');
1513
const { now } = require('internal/perf/utils');
1614
const { enqueue, bufferUserTiming } = require('internal/perf/observe');
1715
const nodeTiming = require('internal/perf/nodetiming');
@@ -35,7 +33,6 @@ const {
3533

3634
const { structuredClone } = require('internal/structured_clone');
3735
const {
38-
kEmptyObject,
3936
lazyDOMException,
4037
kEnumerableProperty,
4138
} = require('internal/util');
@@ -69,27 +66,33 @@ function getMark(name) {
6966
return ts;
7067
}
7168

72-
class PerformanceMark {
73-
constructor(name, options = kEmptyObject) {
74-
if (arguments.length === 0) {
69+
const kEmptyArg = Symbol('kEmptyArg');
70+
71+
class PerformanceMark extends PerformanceEntry {
72+
constructor(name = kEmptyArg, options = undefined) {
73+
if (name === kEmptyArg) {
7574
throw new ERR_MISSING_ARGS('name');
7675
}
7776
name = `${name}`;
78-
options ??= kEmptyObject;
7977
if (nodeTimingReadOnlyAttributes.has(name))
8078
throw new ERR_INVALID_ARG_VALUE('name', name);
81-
validateObject(options, 'options');
82-
const startTime = options.startTime ?? now();
79+
if (options !== undefined) {
80+
validateObject(options, 'options');
81+
}
82+
const startTime = options?.startTime ?? now();
8383
validateNumber(startTime, 'startTime');
8484
if (startTime < 0)
8585
throw new ERR_PERFORMANCE_INVALID_TIMESTAMP(startTime);
8686
markTimings.set(name, startTime);
8787

88-
let detail = options.detail;
88+
let detail = options?.detail;
89+
// The usage of != is intentional, we want to skip structuredClone
90+
// for both undefined and null
8991
detail = detail != null ?
9092
structuredClone(detail) :
9193
null;
92-
initPerformanceEntry(this, name, 'mark', startTime, 0);
94+
95+
super(kSkipThrow, name, 'mark', startTime, 0);
9396
this[kDetail] = detail;
9497
}
9598

@@ -108,8 +111,7 @@ class PerformanceMark {
108111
};
109112
}
110113
}
111-
ObjectSetPrototypeOf(PerformanceMark, PerformanceEntry);
112-
ObjectSetPrototypeOf(PerformanceMark.prototype, PerformanceEntry.prototype);
114+
113115
ObjectDefineProperties(PerformanceMark.prototype, {
114116
detail: kEnumerableProperty,
115117
[SymbolToStringTag]: {
@@ -120,8 +122,18 @@ ObjectDefineProperties(PerformanceMark.prototype, {
120122
});
121123

122124
class PerformanceMeasure extends PerformanceEntry {
123-
constructor() {
124-
throw new ERR_ILLEGAL_CONSTRUCTOR();
125+
constructor(
126+
skipThrowSymbol = undefined,
127+
name = undefined,
128+
type = undefined,
129+
start = undefined,
130+
duration = undefined,
131+
) {
132+
if (skipThrowSymbol !== kSkipThrow) {
133+
throw new ERR_ILLEGAL_CONSTRUCTOR();
134+
}
135+
136+
super(skipThrowSymbol, name, type, start, duration);
125137
}
126138

127139
get detail() {
@@ -139,10 +151,11 @@ ObjectDefineProperties(PerformanceMeasure.prototype, {
139151
});
140152

141153
function createPerformanceMeasure(name, start, duration, detail) {
142-
return ReflectConstruct(function PerformanceMeasure() {
143-
initPerformanceEntry(this, name, 'measure', start, duration);
144-
this[kDetail] = detail;
145-
}, [], PerformanceMeasure);
154+
const measure = new PerformanceMeasure(kSkipThrow, name, 'measure', start, duration);
155+
156+
measure[kDetail] = detail;
157+
158+
return measure;
146159
}
147160

148161
function mark(name, options) {

0 commit comments

Comments
 (0)