Skip to content

Commit d9d4152

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 perpetuatlly growing the entries buffer.
1 parent 0951c38 commit d9d4152

File tree

2 files changed

+178
-80
lines changed

2 files changed

+178
-80
lines changed

packages/react-reconciler/src/SchedulingProfiler.js

Lines changed: 96 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -20,31 +20,62 @@ 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 (supportsUserTiming) {
29+
const CHECK_V3_MARK = '__v3';
30+
const markOptions = {};
31+
// $FlowFixMe: Ignore Flow complaining about needing a value
32+
Object.defineProperty(markOptions, 'startTime', {
33+
get: function() {
34+
supportsUserTimingV3 = true;
35+
return 0;
36+
},
37+
set: function() {},
38+
});
39+
40+
try {
41+
// $FlowFixMe: Flow expects the User Timing level 2 API.
42+
performance.mark(CHECK_V3_MARK, markOptions);
43+
} catch (error) {
44+
// Ignore
45+
} finally {
46+
performance.clearMarks(CHECK_V3_MARK);
47+
}
48+
}
2449

2550
function formatLanes(laneOrLanes: Lane | Lanes): string {
2651
return ((laneOrLanes: any): number).toString();
2752
}
2853

2954
// Create a mark on React initialization
3055
if (enableSchedulingProfiler) {
31-
if (supportsUserTiming) {
32-
performance.mark(`--react-init-${ReactVersion}`);
56+
if (supportsUserTimingV3) {
57+
const name = `--react-init-${ReactVersion}`;
58+
performance.mark(name);
59+
performance.clearMarks(name);
3360
}
3461
}
3562

3663
export function markCommitStarted(lanes: Lanes): void {
3764
if (enableSchedulingProfiler) {
38-
if (supportsUserTiming) {
39-
performance.mark(`--commit-start-${formatLanes(lanes)}`);
65+
if (supportsUserTimingV3) {
66+
const name = `--commit-start-${formatLanes(lanes)}`;
67+
performance.mark(name);
68+
performance.clearMarks(name);
4069
}
4170
}
4271
}
4372

4473
export function markCommitStopped(): void {
4574
if (enableSchedulingProfiler) {
46-
if (supportsUserTiming) {
47-
performance.mark('--commit-stop');
75+
if (supportsUserTimingV3) {
76+
const name = '--commit-stop';
77+
performance.mark(name);
78+
performance.clearMarks(name);
4879
}
4980
}
5081
}
@@ -63,103 +94,133 @@ function getWakeableID(wakeable: Wakeable): number {
6394

6495
export function markComponentSuspended(fiber: Fiber, wakeable: Wakeable): void {
6596
if (enableSchedulingProfiler) {
66-
if (supportsUserTiming) {
97+
if (supportsUserTimingV3) {
6798
const id = getWakeableID(wakeable);
6899
const componentName = getComponentName(fiber.type) || 'Unknown';
69100
// TODO Add component stack id
70-
performance.mark(`--suspense-suspend-${id}-${componentName}`);
101+
let name = `--suspense-suspend-${id}-${componentName}`;
102+
performance.mark(name);
103+
performance.clearMarks(name);
71104
wakeable.then(
72-
() => performance.mark(`--suspense-resolved-${id}-${componentName}`),
73-
() => performance.mark(`--suspense-rejected-${id}-${componentName}`),
105+
() => {
106+
name = `--suspense-resolved-${id}-${componentName}`;
107+
performance.mark(name);
108+
performance.clearMarks(name);
109+
},
110+
() => {
111+
name = `--suspense-rejected-${id}-${componentName}`;
112+
performance.mark(name);
113+
performance.clearMarks(name);
114+
},
74115
);
75116
}
76117
}
77118
}
78119

79120
export function markLayoutEffectsStarted(lanes: Lanes): void {
80121
if (enableSchedulingProfiler) {
81-
if (supportsUserTiming) {
82-
performance.mark(`--layout-effects-start-${formatLanes(lanes)}`);
122+
if (supportsUserTimingV3) {
123+
const name = `--layout-effects-start-${formatLanes(lanes)}`;
124+
performance.mark(name);
125+
performance.clearMarks(name);
83126
}
84127
}
85128
}
86129
87130
export function markLayoutEffectsStopped(): void {
88131
if (enableSchedulingProfiler) {
89-
if (supportsUserTiming) {
90-
performance.mark('--layout-effects-stop');
132+
if (supportsUserTimingV3) {
133+
const name = '--layout-effects-stop';
134+
performance.mark(name);
135+
performance.clearMarks(name);
91136
}
92137
}
93138
}
94139
95140
export function markPassiveEffectsStarted(lanes: Lanes): void {
96141
if (enableSchedulingProfiler) {
97-
if (supportsUserTiming) {
98-
performance.mark(`--passive-effects-start-${formatLanes(lanes)}`);
142+
if (supportsUserTimingV3) {
143+
const name = `--passive-effects-start-${formatLanes(lanes)}`;
144+
performance.mark(name);
145+
performance.clearMarks(name);
99146
}
100147
}
101148
}
102149
103150
export function markPassiveEffectsStopped(): void {
104151
if (enableSchedulingProfiler) {
105-
if (supportsUserTiming) {
106-
performance.mark('--passive-effects-stop');
152+
if (supportsUserTimingV3) {
153+
const name = '--passive-effects-stop';
154+
performance.mark(name);
155+
performance.clearMarks(name);
107156
}
108157
}
109158
}
110159
111160
export function markRenderStarted(lanes: Lanes): void {
112161
if (enableSchedulingProfiler) {
113-
if (supportsUserTiming) {
114-
performance.mark(`--render-start-${formatLanes(lanes)}`);
162+
if (supportsUserTimingV3) {
163+
const name = `--render-start-${formatLanes(lanes)}`;
164+
performance.mark(name);
165+
performance.clearMarks(name);
115166
}
116167
}
117168
}
118169
119170
export function markRenderYielded(): void {
120171
if (enableSchedulingProfiler) {
121-
if (supportsUserTiming) {
122-
performance.mark('--render-yield');
172+
if (supportsUserTimingV3) {
173+
const name = '--render-yield';
174+
performance.mark(name);
175+
performance.clearMarks(name);
123176
}
124177
}
125178
}
126179
127180
export function markRenderStopped(): void {
128181
if (enableSchedulingProfiler) {
129-
if (supportsUserTiming) {
130-
performance.mark('--render-stop');
182+
if (supportsUserTimingV3) {
183+
const name = '--render-stop';
184+
performance.mark(name);
185+
performance.clearMarks(name);
131186
}
132187
}
133188
}
134189
135190
export function markRenderScheduled(lane: Lane): void {
136191
if (enableSchedulingProfiler) {
137-
if (supportsUserTiming) {
138-
performance.mark(`--schedule-render-${formatLanes(lane)}`);
192+
if (supportsUserTimingV3) {
193+
const name = `--schedule-render-${formatLanes(lane)}`;
194+
performance.mark(name);
195+
performance.clearMarks(name);
139196
}
140197
}
141198
}
142199
143200
export function markForceUpdateScheduled(fiber: Fiber, lane: Lane): void {
144201
if (enableSchedulingProfiler) {
145-
if (supportsUserTiming) {
202+
if (supportsUserTimingV3) {
146203
const componentName = getComponentName(fiber.type) || 'Unknown';
147204
// TODO Add component stack id
148-
performance.mark(
149-
`--schedule-forced-update-${formatLanes(lane)}-${componentName}`,
150-
);
205+
const name = `--schedule-forced-update-${formatLanes(
206+
lane,
207+
)}-${componentName}`;
208+
performance.mark(name);
209+
performance.clearMarks(name);
151210
}
152211
}
153212
}
154213
155214
export function markStateUpdateScheduled(fiber: Fiber, lane: Lane): void {
156215
if (enableSchedulingProfiler) {
157-
if (supportsUserTiming) {
216+
if (supportsUserTimingV3) {
158217
const componentName = getComponentName(fiber.type) || 'Unknown';
159218
// TODO Add component stack id
160-
performance.mark(
161-
`--schedule-state-update-${formatLanes(lane)}-${componentName}`,
162-
);
219+
const name = `--schedule-state-update-${formatLanes(
220+
lane,
221+
)}-${componentName}`;
222+
performance.mark(name);
223+
performance.clearMarks(name);
163224
}
164225
}
165226
}

0 commit comments

Comments
 (0)