Skip to content

Commit 8657869

Browse files
authored
Separate Tracks for Components and Phases (#31525)
Previously we were showing Components inside each lane track but that meant that as soon as you expanded a lane you couldn't see the other line so you couldn't get an overview over how well things were scheduled. This instead moves all the Components into a single top-level track and renames the previous one to a "Scheduler" track group. <img width="1352" alt="Screenshot 2024-11-12 at 8 26 05 PM" src="https://github.com/user-attachments/assets/590bc6d3-3540-4ee4-b474-5d733b8d8d8d"> That way you can get an overview over what React is working on first and then right below see which Component is being worked on. Ideally the "Scheduler" track would be always expanded since each Track is always just a single row. Now you have to expand each lane to see the labels but then you're wasting a lot of vertical real estate. There's currently no option to create this with the Chrome performance.measure extensions. <img width="1277" alt="Screenshot 2024-11-12 at 8 26 16 PM" src="https://github.com/user-attachments/assets/4fc39e35-10ec-4452-ad32-c1c2e6b5e1a8">
1 parent b15135b commit 8657869

File tree

1 file changed

+65
-53
lines changed

1 file changed

+65
-53
lines changed

Diff for: packages/react-reconciler/src/ReactFiberPerformanceTrack.js

+65-53
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,13 @@ const supportsUserTiming =
2121
// $FlowFixMe[method-unbinding]
2222
typeof performance.measure === 'function';
2323

24-
const TRACK_GROUP = 'Components ⚛';
24+
const COMPONENTS_TRACK = 'Components ⚛';
2525

2626
// Reused to avoid thrashing the GC.
2727
const reusableComponentDevToolDetails = {
2828
dataType: 'track-entry',
2929
color: 'primary',
30-
track: 'Blocking', // Lane
31-
trackGroup: TRACK_GROUP,
30+
track: COMPONENTS_TRACK,
3231
};
3332
const reusableComponentOptions = {
3433
start: -0,
@@ -38,9 +37,24 @@ const reusableComponentOptions = {
3837
},
3938
};
4039

40+
const LANES_TRACK_GROUP = 'Scheduler ⚛';
41+
42+
const reusableLaneDevToolDetails = {
43+
dataType: 'track-entry',
44+
color: 'primary',
45+
track: 'Blocking', // Lane
46+
trackGroup: LANES_TRACK_GROUP,
47+
};
48+
const reusableLaneOptions = {
49+
start: -0,
50+
end: -0,
51+
detail: {
52+
devtools: reusableLaneDevToolDetails,
53+
},
54+
};
55+
4156
export function setCurrentTrackFromLanes(lanes: number): void {
42-
reusableComponentDevToolDetails.track =
43-
getGroupNameOfHighestPriorityLane(lanes);
57+
reusableLaneDevToolDetails.track = getGroupNameOfHighestPriorityLane(lanes);
4458
}
4559

4660
export function logComponentRender(
@@ -107,21 +121,20 @@ export function logBlockingStart(
107121
renderStartTime: number,
108122
): void {
109123
if (supportsUserTiming) {
110-
reusableComponentDevToolDetails.track = 'Blocking';
124+
reusableLaneDevToolDetails.track = 'Blocking';
111125
if (eventTime > 0 && eventType !== null) {
112126
// Log the time from the event timeStamp until we called setState.
113-
reusableComponentDevToolDetails.color = 'secondary-dark';
114-
reusableComponentOptions.start = eventTime;
115-
reusableComponentOptions.end =
116-
updateTime > 0 ? updateTime : renderStartTime;
117-
performance.measure(eventType, reusableComponentOptions);
127+
reusableLaneDevToolDetails.color = 'secondary-dark';
128+
reusableLaneOptions.start = eventTime;
129+
reusableLaneOptions.end = updateTime > 0 ? updateTime : renderStartTime;
130+
performance.measure(eventType, reusableLaneOptions);
118131
}
119132
if (updateTime > 0) {
120133
// Log the time from when we called setState until we started rendering.
121-
reusableComponentDevToolDetails.color = 'primary-light';
122-
reusableComponentOptions.start = updateTime;
123-
reusableComponentOptions.end = renderStartTime;
124-
performance.measure('Blocked', reusableComponentOptions);
134+
reusableLaneDevToolDetails.color = 'primary-light';
135+
reusableLaneOptions.start = updateTime;
136+
reusableLaneOptions.end = renderStartTime;
137+
performance.measure('Blocked', reusableLaneOptions);
125138
}
126139
}
127140
}
@@ -134,43 +147,42 @@ export function logTransitionStart(
134147
renderStartTime: number,
135148
): void {
136149
if (supportsUserTiming) {
137-
reusableComponentDevToolDetails.track = 'Transition';
150+
reusableLaneDevToolDetails.track = 'Transition';
138151
if (eventTime > 0 && eventType !== null) {
139152
// Log the time from the event timeStamp until we started a transition.
140-
reusableComponentDevToolDetails.color = 'secondary-dark';
141-
reusableComponentOptions.start = eventTime;
142-
reusableComponentOptions.end =
153+
reusableLaneDevToolDetails.color = 'secondary-dark';
154+
reusableLaneOptions.start = eventTime;
155+
reusableLaneOptions.end =
143156
startTime > 0
144157
? startTime
145158
: updateTime > 0
146159
? updateTime
147160
: renderStartTime;
148-
performance.measure(eventType, reusableComponentOptions);
161+
performance.measure(eventType, reusableLaneOptions);
149162
}
150163
if (startTime > 0) {
151164
// Log the time from when we started an async transition until we called setState or started rendering.
152-
reusableComponentDevToolDetails.color = 'primary-dark';
153-
reusableComponentOptions.start = startTime;
154-
reusableComponentOptions.end =
155-
updateTime > 0 ? updateTime : renderStartTime;
156-
performance.measure('Action', reusableComponentOptions);
165+
reusableLaneDevToolDetails.color = 'primary-dark';
166+
reusableLaneOptions.start = startTime;
167+
reusableLaneOptions.end = updateTime > 0 ? updateTime : renderStartTime;
168+
performance.measure('Action', reusableLaneOptions);
157169
}
158170
if (updateTime > 0) {
159171
// Log the time from when we called setState until we started rendering.
160-
reusableComponentDevToolDetails.color = 'primary-light';
161-
reusableComponentOptions.start = updateTime;
162-
reusableComponentOptions.end = renderStartTime;
163-
performance.measure('Blocked', reusableComponentOptions);
172+
reusableLaneDevToolDetails.color = 'primary-light';
173+
reusableLaneOptions.start = updateTime;
174+
reusableLaneOptions.end = renderStartTime;
175+
performance.measure('Blocked', reusableLaneOptions);
164176
}
165177
}
166178
}
167179

168180
export function logRenderPhase(startTime: number, endTime: number): void {
169181
if (supportsUserTiming) {
170-
reusableComponentDevToolDetails.color = 'primary-dark';
171-
reusableComponentOptions.start = startTime;
172-
reusableComponentOptions.end = endTime;
173-
performance.measure('Render', reusableComponentOptions);
182+
reusableLaneDevToolDetails.color = 'primary-dark';
183+
reusableLaneOptions.start = startTime;
184+
reusableLaneOptions.end = endTime;
185+
performance.measure('Render', reusableLaneOptions);
174186
}
175187
}
176188

@@ -180,10 +192,10 @@ export function logSuspenseThrottlePhase(
180192
): void {
181193
// This was inside a throttled Suspense boundary commit.
182194
if (supportsUserTiming) {
183-
reusableComponentDevToolDetails.color = 'secondary-light';
184-
reusableComponentOptions.start = startTime;
185-
reusableComponentOptions.end = endTime;
186-
performance.measure('Throttled', reusableComponentOptions);
195+
reusableLaneDevToolDetails.color = 'secondary-light';
196+
reusableLaneOptions.start = startTime;
197+
reusableLaneOptions.end = endTime;
198+
performance.measure('Throttled', reusableLaneOptions);
187199
}
188200
}
189201

@@ -193,28 +205,28 @@ export function logSuspendedCommitPhase(
193205
): void {
194206
// This means the commit was suspended on CSS or images.
195207
if (supportsUserTiming) {
196-
reusableComponentDevToolDetails.color = 'secondary-light';
197-
reusableComponentOptions.start = startTime;
198-
reusableComponentOptions.end = endTime;
199-
performance.measure('Suspended', reusableComponentOptions);
208+
reusableLaneDevToolDetails.color = 'secondary-light';
209+
reusableLaneOptions.start = startTime;
210+
reusableLaneOptions.end = endTime;
211+
performance.measure('Suspended', reusableLaneOptions);
200212
}
201213
}
202214

203215
export function logCommitPhase(startTime: number, endTime: number): void {
204216
if (supportsUserTiming) {
205-
reusableComponentDevToolDetails.color = 'secondary-dark';
206-
reusableComponentOptions.start = startTime;
207-
reusableComponentOptions.end = endTime;
208-
performance.measure('Commit', reusableComponentOptions);
217+
reusableLaneDevToolDetails.color = 'secondary-dark';
218+
reusableLaneOptions.start = startTime;
219+
reusableLaneOptions.end = endTime;
220+
performance.measure('Commit', reusableLaneOptions);
209221
}
210222
}
211223

212224
export function logPaintYieldPhase(startTime: number, endTime: number): void {
213225
if (supportsUserTiming) {
214-
reusableComponentDevToolDetails.color = 'secondary-light';
215-
reusableComponentOptions.start = startTime;
216-
reusableComponentOptions.end = endTime;
217-
performance.measure('Waiting for Paint', reusableComponentOptions);
226+
reusableLaneDevToolDetails.color = 'secondary-light';
227+
reusableLaneOptions.start = startTime;
228+
reusableLaneOptions.end = endTime;
229+
performance.measure('Waiting for Paint', reusableLaneOptions);
218230
}
219231
}
220232

@@ -223,9 +235,9 @@ export function logPassiveCommitPhase(
223235
endTime: number,
224236
): void {
225237
if (supportsUserTiming) {
226-
reusableComponentDevToolDetails.color = 'secondary-dark';
227-
reusableComponentOptions.start = startTime;
228-
reusableComponentOptions.end = endTime;
229-
performance.measure('Remaining Effects', reusableComponentOptions);
238+
reusableLaneDevToolDetails.color = 'secondary-dark';
239+
reusableLaneOptions.start = startTime;
240+
reusableLaneOptions.end = endTime;
241+
performance.measure('Remaining Effects', reusableLaneOptions);
230242
}
231243
}

0 commit comments

Comments
 (0)