Skip to content

Commit 7ea98fb

Browse files
joyeecheungtargos
authored andcommitted
perf_hooks: refactor perf_hooks for snapshot building
- Move Performance and InternalPerformance to a new lib/internal/perf/performance.js - Move now() getMilestoneTimestamp() into lib/internal/perf/utils.js - Rename lib/internal/perf/perf.js to lib/internal/perf/performance_entry.js - Refresh time origin at startup (this means the time origins could differ between snapshot building time and snapshot creation time) PR-URL: #38971 Refs: #35711 Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent 0e55cb7 commit 7ea98fb

15 files changed

Lines changed: 224 additions & 183 deletions

‎lib/internal/bootstrap/pre_execution.js‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ function prepareMainThreadExecution(expandArgv1 = false) {
2727
// Patch the process object with legacy properties and normalizations
2828
patchProcessObject(expandArgv1);
2929
setupTraceCategoryState();
30+
setupPerfHooks();
3031
setupInspectorHooks();
3132
setupWarningHandler();
3233

@@ -222,6 +223,11 @@ function setupTraceCategoryState() {
222223
toggleTraceCategoryState(isTraceCategoryEnabled('node.async_hooks'));
223224
}
224225

226+
functionsetupPerfHooks(){
227+
require('internal/perf/performance').refreshTimeOrigin();
228+
require('internal/perf/utils').refreshTimeOrigin();
229+
}
230+
225231
functionsetupInspectorHooks(){
226232
// If Debugger.setAsyncCallStackDepth is sent during bootstrap,
227233
// we cannot immediately call into JS to enable the hooks, which could
@@ -474,6 +480,7 @@ module.exports = {
474480
setupCoverageHooks,
475481
setupWarningHandler,
476482
setupDebugEnv,
483+
setupPerfHooks,
477484
prepareMainThreadExecution,
478485
initializeDeprecations,
479486
initializeESMLoader,

‎lib/internal/http.js‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const {
99

1010
const{ setUnrefTimeout }=require('internal/timers');
1111

12-
const{ InternalPerformanceEntry }=require('internal/perf/perf');
12+
const{ InternalPerformanceEntry }=require('internal/perf/performance_entry');
1313

1414
const{
1515
enqueue,

‎lib/internal/main/worker_thread.js‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ const {
1818
setupInspectorHooks,
1919
setupWarningHandler,
2020
setupDebugEnv,
21+
setupPerfHooks,
2122
initializeDeprecations,
2223
initializeWASI,
2324
initializeCJSLoader,
@@ -114,6 +115,7 @@ port.on('message', (message) => {
114115
}=message;
115116

116117
setupTraceCategoryState();
118+
setupPerfHooks();
117119
initializeReport();
118120
if(manifestSrc){
119121
require('internal/process/policy').setup(manifestSrc,manifestURL);

‎lib/internal/perf/event_loop_utilization.js‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
constnodeTiming=require('internal/perf/nodetiming');
44

5-
const{ now }=require('internal/perf/perf');
5+
const{ now }=require('internal/perf/utils');
66

77
functioneventLoopUtilization(util1,util2){
88
constls=nodeTiming.loopStart;

‎lib/internal/perf/nodetiming.js‎

Lines changed: 4 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,14 @@
33
const{
44
ObjectDefineProperties,
55
ObjectSetPrototypeOf,
6-
SafeArrayIterator,
7-
SafeSet,
86
}=primordials;
97

8+
const{ PerformanceEntry }=require('internal/perf/performance_entry');
9+
1010
const{
11-
PerformanceEntry,
12-
kReadOnlyAttributes,
1311
now,
14-
}=require('internal/perf/perf');
12+
getMilestoneTimestamp,
13+
}=require('internal/perf/utils');
1514

1615
const{
1716
customInspectSymbol: kInspect,
@@ -29,26 +28,8 @@ const {
2928
NODE_PERFORMANCE_MILESTONE_ENVIRONMENT
3029
},
3130
loopIdleTime,
32-
milestones,
33-
timeOrigin,
3431
}=internalBinding('performance');
3532

36-
functiongetMilestoneTimestamp(milestoneIdx){
37-
constns=milestones[milestoneIdx];
38-
if(ns===-1)
39-
returnns;
40-
returnns/1e6-timeOrigin;
41-
}
42-
43-
constreadOnlyAttributes=newSafeSet(newSafeArrayIterator([
44-
'nodeStart',
45-
'v8Start',
46-
'environment',
47-
'loopStart',
48-
'loopExit',
49-
'bootstrapComplete',
50-
]));
51-
5233
classPerformanceNodeTiming{
5334
constructor(){
5435
ObjectDefineProperties(this,{
@@ -159,10 +140,6 @@ class PerformanceNodeTiming {
159140
idleTime: this.idleTime,
160141
};
161142
}
162-
163-
staticget[kReadOnlyAttributes](){
164-
returnreadOnlyAttributes;
165-
}
166143
}
167144

168145
ObjectSetPrototypeOf(

‎lib/internal/perf/observe.js‎

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ const {
3131
const{
3232
InternalPerformanceEntry,
3333
isPerformanceEntry,
34-
}=require('internal/perf/perf');
34+
}=require('internal/perf/performance_entry');
3535

3636
const{
3737
codes: {
@@ -174,11 +174,13 @@ class PerformanceObserverEntryList {
174174
}
175175

176176
classPerformanceObserver{
177-
[kBuffer]=[];
178-
[kEntryTypes]=newSafeSet();
179-
[kType]=undefined;
180-
181177
constructor(callback){
178+
// TODO(joyeecheung): V8 snapshot does not support instance member
179+
// initializers for now:
180+
// https://bugs.chromium.org/p/v8/issues/detail?id=10704
181+
this[kBuffer]=[];
182+
this[kEntryTypes]=newSafeSet();
183+
this[kType]=undefined;
182184
validateCallback(callback);
183185
this[kCallback]=callback;
184186
}

‎lib/internal/perf/performance.js‎

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
'use strict';
2+
3+
const{
4+
ObjectDefineProperty,
5+
ObjectDefineProperties,
6+
ObjectSetPrototypeOf,
7+
TypeError,
8+
}=primordials;
9+
10+
const{
11+
EventTarget,
12+
}=require('internal/event_target');
13+
14+
const{ now }=require('internal/perf/utils');
15+
16+
const{
17+
mark,
18+
measure,
19+
clearMarks,
20+
}=require('internal/perf/usertiming');
21+
22+
consteventLoopUtilization=require('internal/perf/event_loop_utilization');
23+
constnodeTiming=require('internal/perf/nodetiming');
24+
consttimerify=require('internal/perf/timerify');
25+
const{customInspectSymbol: kInspect}=require('internal/util');
26+
const{ inspect }=require('util');
27+
28+
const{
29+
getTimeOriginTimestamp
30+
}=internalBinding('performance');
31+
32+
classPerformanceextendsEventTarget{
33+
constructor(){
34+
// eslint-disable-next-line no-restricted-syntax
35+
thrownewTypeError('Illegal constructor');
36+
}
37+
38+
[kInspect](depth,options){
39+
if(depth<0)returnthis;
40+
41+
constopts={
42+
...options,
43+
depth: options.depth==null ? null : options.depth-1
44+
};
45+
46+
return`Performance ${inspect({
47+
nodeTiming: this.nodeTiming,
48+
timeOrigin: this.timeOrigin,
49+
},opts)}`;
50+
}
51+
52+
}
53+
54+
functiontoJSON(){
55+
return{
56+
nodeTiming: this.nodeTiming,
57+
timeOrigin: this.timeOrigin,
58+
eventLoopUtilization: this.eventLoopUtilization()
59+
};
60+
}
61+
62+
classInternalPerformanceextendsEventTarget{}
63+
InternalPerformance.prototype.constructor=Performance.prototype.constructor;
64+
ObjectSetPrototypeOf(InternalPerformance.prototype,Performance.prototype);
65+
66+
ObjectDefineProperties(Performance.prototype,{
67+
clearMarks: {
68+
configurable: true,
69+
enumerable: false,
70+
value: clearMarks,
71+
},
72+
eventLoopUtilization: {
73+
configurable: true,
74+
enumerable: false,
75+
value: eventLoopUtilization,
76+
},
77+
mark: {
78+
configurable: true,
79+
enumerable: false,
80+
value: mark,
81+
},
82+
measure: {
83+
configurable: true,
84+
enumerable: false,
85+
value: measure,
86+
},
87+
nodeTiming: {
88+
configurable: true,
89+
enumerable: false,
90+
value: nodeTiming,
91+
},
92+
now: {
93+
configurable: true,
94+
enumerable: false,
95+
value: now,
96+
},
97+
timerify: {
98+
configurable: true,
99+
enumerable: false,
100+
value: timerify,
101+
},
102+
// This would be updated during pre-execution in case
103+
// the process is launched from a snapshot.
104+
// TODO(joyeecheung): we may want to warn about access to
105+
// this during snapshot building.
106+
timeOrigin: {
107+
configurable: true,
108+
enumerable: true,
109+
value: getTimeOriginTimestamp(),
110+
},
111+
toJSON: {
112+
configurable: true,
113+
enumerable: true,
114+
value: toJSON,
115+
}
116+
});
117+
118+
functionrefreshTimeOrigin(){
119+
ObjectDefineProperty(Performance.prototype,'timeOrigin',{
120+
configurable: true,
121+
enumerable: true,
122+
value: getTimeOriginTimestamp(),
123+
});
124+
}
125+
126+
module.exports={
127+
InternalPerformance,
128+
refreshTimeOrigin
129+
};
Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,6 @@ const {
66
TypeError,
77
}=primordials;
88

9-
const{
10-
timeOrigin,
11-
}=internalBinding('performance');
12-
139
const{
1410
customInspectSymbol: kInspect,
1511
}=require('internal/util');
@@ -21,12 +17,6 @@ const kType = Symbol('kType');
2117
constkStart=Symbol('kStart');
2218
constkDuration=Symbol('kDuration');
2319
constkDetail=Symbol('kDetail');
24-
constkReadOnlyAttributes=Symbol('kReadOnlyAttributes');
25-
26-
functionnow(){
27-
consthr=process.hrtime();
28-
return(hr[0]*1000+hr[1]/1e6)-timeOrigin;
29-
}
3020

3121
functionisPerformanceEntry(obj){
3222
returnobj?.[kName]!==undefined;
@@ -88,7 +78,5 @@ ObjectSetPrototypeOf(
8878
module.exports={
8979
InternalPerformanceEntry,
9080
PerformanceEntry,
91-
kReadOnlyAttributes,
9281
isPerformanceEntry,
93-
now,
9482
};

‎lib/internal/perf/timerify.js‎

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,8 @@ const {
99
Symbol,
1010
}=primordials;
1111

12-
const{
13-
InternalPerformanceEntry,
14-
now,
15-
}=require('internal/perf/perf');
12+
const{ InternalPerformanceEntry }=require('internal/perf/performance_entry');
13+
const{ now }=require('internal/perf/utils');
1614

1715
const{
1816
validateFunction,

‎lib/internal/perf/usertiming.js‎

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,13 @@
33
const{
44
ObjectKeys,
55
SafeMap,
6+
SafeSet,
7+
SafeArrayIterator,
68
}=primordials;
79

8-
const{
9-
InternalPerformanceEntry,
10-
kReadOnlyAttributes,
11-
now,
12-
}=require('internal/perf/perf');
13-
10+
const{ InternalPerformanceEntry }=require('internal/perf/performance_entry');
11+
const{ now }=require('internal/perf/utils');
1412
const{ enqueue }=require('internal/perf/observe');
15-
1613
constnodeTiming=require('internal/perf/nodetiming');
1714

1815
const{
@@ -31,8 +28,15 @@ const {
3128
}=require('internal/errors');
3229

3330
constmarks=newSafeMap();
34-
constnodeTimingReadOnlyAttributes=
35-
nodeTiming.constructor[kReadOnlyAttributes];
31+
32+
constnodeTimingReadOnlyAttributes=newSafeSet(newSafeArrayIterator([
33+
'nodeStart',
34+
'v8Start',
35+
'environment',
36+
'loopStart',
37+
'loopExit',
38+
'bootstrapComplete',
39+
]));
3640

3741
functiongetMark(name){
3842
if(name===undefined)return;

0 commit comments

Comments
 (0)