Skip to content

Commit faf999f

Browse files
author
Brian Vaughn
committed
Update scheduling profiler to require User Timing level 3
Browsers that implement User Timing level 2 (e.g. Firefox) apparently struggle to keep up with the number of marks the scheduling profiler is logging. To avoid this, the feature detection has been updated to require User Timing level 3 support. In addition to this, marks are cleared immediately after being logged to avoid perpetually growing the entries buffer.
1 parent 0951c38 commit faf999f

File tree

2 files changed

+180
-80
lines changed

2 files changed

+180
-80
lines changed

packages/react-reconciler/src/SchedulingProfiler.js

Lines changed: 98 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -20,31 +20,64 @@ import getComponentName from 'shared/getComponentName';
2020
* require.
2121
*/
2222
const supportsUserTiming =
23-
typeof performance !== 'undefined' && typeof performance.mark === 'function';
23+
typeof performance !== 'undefined' &&
24+
typeof performance.mark === 'function' &&
25+
typeof performance.clearMarks === 'function';
26+
27+
let supportsUserTimingV3 = false;
28+
if (enableSchedulingProfiler) {
29+
if (supportsUserTiming) {
30+
const CHECK_V3_MARK = '__v3';
31+
const markOptions = {};
32+
// $FlowFixMe: Ignore Flow complaining about needing a value
33+
Object.defineProperty(markOptions, 'startTime', {
34+
get: function() {
35+
supportsUserTimingV3 = true;
36+
return 0;
37+
},
38+
set: function() {},
39+
});
40+
41+
try {
42+
// $FlowFixMe: Flow expects the User Timing level 2 API.
43+
performance.mark(CHECK_V3_MARK, markOptions);
44+
} catch (error) {
45+
// Ignore
46+
} finally {
47+
performance.clearMarks(CHECK_V3_MARK);
48+
}
49+
}
50+
}
2451

2552
function formatLanes(laneOrLanes: Lane | Lanes): string {
2653
return ((laneOrLanes: any): number).toString();
2754
}
2855

2956
// Create a mark on React initialization
3057
if (enableSchedulingProfiler) {
31-
if (supportsUserTiming) {
32-
performance.mark(`--react-init-${ReactVersion}`);
58+
if (supportsUserTimingV3) {
59+
const name = `--react-init-${ReactVersion}`;
60+
performance.mark(name);
61+
performance.clearMarks(name);
3362
}
3463
}
3564

3665
export function markCommitStarted(lanes: Lanes): void {
3766
if (enableSchedulingProfiler) {
38-
if (supportsUserTiming) {
39-
performance.mark(`--commit-start-${formatLanes(lanes)}`);
67+
if (supportsUserTimingV3) {
68+
const name = `--commit-start-${formatLanes(lanes)}`;
69+
performance.mark(name);
70+
performance.clearMarks(name);
4071
}
4172
}
4273
}
4374

4475
export function markCommitStopped(): void {
4576
if (enableSchedulingProfiler) {
46-
if (supportsUserTiming) {
47-
performance.mark('--commit-stop');
77+
if (supportsUserTimingV3) {
78+
const name = '--commit-stop';
79+
performance.mark(name);
80+
performance.clearMarks(name);
4881
}
4982
}
5083
}
@@ -63,103 +96,133 @@ function getWakeableID(wakeable: Wakeable): number {
6396

6497
export function markComponentSuspended(fiber: Fiber, wakeable: Wakeable): void {
6598
if (enableSchedulingProfiler) {
66-
if (supportsUserTiming) {
99+
if (supportsUserTimingV3) {
67100
const id = getWakeableID(wakeable);
68101
const componentName = getComponentName(fiber.type) || 'Unknown';
69102
// TODO Add component stack id
70-
performance.mark(`--suspense-suspend-${id}-${componentName}`);
103+
let name = `--suspense-suspend-${id}-${componentName}`;
104+
performance.mark(name);
105+
performance.clearMarks(name);
71106
wakeable.then(
72-
() => performance.mark(`--suspense-resolved-${id}-${componentName}`),
73-
() => performance.mark(`--suspense-rejected-${id}-${componentName}`),
107+
() => {
108+
name = `--suspense-resolved-${id}-${componentName}`;
109+
performance.mark(name);
110+
performance.clearMarks(name);
111+
},
112+
() => {
113+
name = `--suspense-rejected-${id}-${componentName}`;
114+
performance.mark(name);
115+
performance.clearMarks(name);
116+
},
74117
);
75118
}
76119
}
77120
}
78121

79122
export function markLayoutEffectsStarted(lanes: Lanes): void {
80123
if (enableSchedulingProfiler) {
81-
if (supportsUserTiming) {
82-
performance.mark(`--layout-effects-start-${formatLanes(lanes)}`);
124+
if (supportsUserTimingV3) {
125+
const name = `--layout-effects-start-${formatLanes(lanes)}`;
126+
performance.mark(name);
127+
performance.clearMarks(name);
83128
}
84129
}
85130
}
86131
87132
export function markLayoutEffectsStopped(): void {
88133
if (enableSchedulingProfiler) {
89-
if (supportsUserTiming) {
90-
performance.mark('--layout-effects-stop');
134+
if (supportsUserTimingV3) {
135+
const name = '--layout-effects-stop';
136+
performance.mark(name);
137+
performance.clearMarks(name);
91138
}
92139
}
93140
}
94141
95142
export function markPassiveEffectsStarted(lanes: Lanes): void {
96143
if (enableSchedulingProfiler) {
97-
if (supportsUserTiming) {
98-
performance.mark(`--passive-effects-start-${formatLanes(lanes)}`);
144+
if (supportsUserTimingV3) {
145+
const name = `--passive-effects-start-${formatLanes(lanes)}`;
146+
performance.mark(name);
147+
performance.clearMarks(name);
99148
}
100149
}
101150
}
102151
103152
export function markPassiveEffectsStopped(): void {
104153
if (enableSchedulingProfiler) {
105-
if (supportsUserTiming) {
106-
performance.mark('--passive-effects-stop');
154+
if (supportsUserTimingV3) {
155+
const name = '--passive-effects-stop';
156+
performance.mark(name);
157+
performance.clearMarks(name);
107158
}
108159
}
109160
}
110161
111162
export function markRenderStarted(lanes: Lanes): void {
112163
if (enableSchedulingProfiler) {
113-
if (supportsUserTiming) {
114-
performance.mark(`--render-start-${formatLanes(lanes)}`);
164+
if (supportsUserTimingV3) {
165+
const name = `--render-start-${formatLanes(lanes)}`;
166+
performance.mark(name);
167+
performance.clearMarks(name);
115168
}
116169
}
117170
}
118171
119172
export function markRenderYielded(): void {
120173
if (enableSchedulingProfiler) {
121-
if (supportsUserTiming) {
122-
performance.mark('--render-yield');
174+
if (supportsUserTimingV3) {
175+
const name = '--render-yield';
176+
performance.mark(name);
177+
performance.clearMarks(name);
123178
}
124179
}
125180
}
126181
127182
export function markRenderStopped(): void {
128183
if (enableSchedulingProfiler) {
129-
if (supportsUserTiming) {
130-
performance.mark('--render-stop');
184+
if (supportsUserTimingV3) {
185+
const name = '--render-stop';
186+
performance.mark(name);
187+
performance.clearMarks(name);
131188
}
132189
}
133190
}
134191
135192
export function markRenderScheduled(lane: Lane): void {
136193
if (enableSchedulingProfiler) {
137-
if (supportsUserTiming) {
138-
performance.mark(`--schedule-render-${formatLanes(lane)}`);
194+
if (supportsUserTimingV3) {
195+
const name = `--schedule-render-${formatLanes(lane)}`;
196+
performance.mark(name);
197+
performance.clearMarks(name);
139198
}
140199
}
141200
}
142201
143202
export function markForceUpdateScheduled(fiber: Fiber, lane: Lane): void {
144203
if (enableSchedulingProfiler) {
145-
if (supportsUserTiming) {
204+
if (supportsUserTimingV3) {
146205
const componentName = getComponentName(fiber.type) || 'Unknown';
147206
// TODO Add component stack id
148-
performance.mark(
149-
`--schedule-forced-update-${formatLanes(lane)}-${componentName}`,
150-
);
207+
const name = `--schedule-forced-update-${formatLanes(
208+
lane,
209+
)}-${componentName}`;
210+
performance.mark(name);
211+
performance.clearMarks(name);
151212
}
152213
}
153214
}
154215
155216
export function markStateUpdateScheduled(fiber: Fiber, lane: Lane): void {
156217
if (enableSchedulingProfiler) {
157-
if (supportsUserTiming) {
218+
if (supportsUserTimingV3) {
158219
const componentName = getComponentName(fiber.type) || 'Unknown';
159220
// TODO Add component stack id
160-
performance.mark(
161-
`--schedule-state-update-${formatLanes(lane)}-${componentName}`,
162-
);
221+
const name = `--schedule-state-update-${formatLanes(
222+
lane,
223+
)}-${componentName}`;
224+
performance.mark(name);
225+
performance.clearMarks(name);
163226
}
164227
}
165228
}

0 commit comments

Comments
 (0)