Skip to content

Commit

Permalink
Separate Tracks for Components and Phases (#31525)
Browse files Browse the repository at this point in the history
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">
  • Loading branch information
sebmarkbage authored Nov 14, 2024
1 parent b15135b commit 8657869
Showing 1 changed file with 65 additions and 53 deletions.
118 changes: 65 additions & 53 deletions packages/react-reconciler/src/ReactFiberPerformanceTrack.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,13 @@ const supportsUserTiming =
// $FlowFixMe[method-unbinding]
typeof performance.measure === 'function';

const TRACK_GROUP = 'Components ⚛';
const COMPONENTS_TRACK = 'Components ⚛';

// Reused to avoid thrashing the GC.
const reusableComponentDevToolDetails = {
dataType: 'track-entry',
color: 'primary',
track: 'Blocking', // Lane
trackGroup: TRACK_GROUP,
track: COMPONENTS_TRACK,
};
const reusableComponentOptions = {
start: -0,
Expand All @@ -38,9 +37,24 @@ const reusableComponentOptions = {
},
};

const LANES_TRACK_GROUP = 'Scheduler ⚛';

const reusableLaneDevToolDetails = {
dataType: 'track-entry',
color: 'primary',
track: 'Blocking', // Lane
trackGroup: LANES_TRACK_GROUP,
};
const reusableLaneOptions = {
start: -0,
end: -0,
detail: {
devtools: reusableLaneDevToolDetails,
},
};

export function setCurrentTrackFromLanes(lanes: number): void {
reusableComponentDevToolDetails.track =
getGroupNameOfHighestPriorityLane(lanes);
reusableLaneDevToolDetails.track = getGroupNameOfHighestPriorityLane(lanes);
}

export function logComponentRender(
Expand Down Expand Up @@ -107,21 +121,20 @@ export function logBlockingStart(
renderStartTime: number,
): void {
if (supportsUserTiming) {
reusableComponentDevToolDetails.track = 'Blocking';
reusableLaneDevToolDetails.track = 'Blocking';
if (eventTime > 0 && eventType !== null) {
// Log the time from the event timeStamp until we called setState.
reusableComponentDevToolDetails.color = 'secondary-dark';
reusableComponentOptions.start = eventTime;
reusableComponentOptions.end =
updateTime > 0 ? updateTime : renderStartTime;
performance.measure(eventType, reusableComponentOptions);
reusableLaneDevToolDetails.color = 'secondary-dark';
reusableLaneOptions.start = eventTime;
reusableLaneOptions.end = updateTime > 0 ? updateTime : renderStartTime;
performance.measure(eventType, reusableLaneOptions);
}
if (updateTime > 0) {
// Log the time from when we called setState until we started rendering.
reusableComponentDevToolDetails.color = 'primary-light';
reusableComponentOptions.start = updateTime;
reusableComponentOptions.end = renderStartTime;
performance.measure('Blocked', reusableComponentOptions);
reusableLaneDevToolDetails.color = 'primary-light';
reusableLaneOptions.start = updateTime;
reusableLaneOptions.end = renderStartTime;
performance.measure('Blocked', reusableLaneOptions);
}
}
}
Expand All @@ -134,43 +147,42 @@ export function logTransitionStart(
renderStartTime: number,
): void {
if (supportsUserTiming) {
reusableComponentDevToolDetails.track = 'Transition';
reusableLaneDevToolDetails.track = 'Transition';
if (eventTime > 0 && eventType !== null) {
// Log the time from the event timeStamp until we started a transition.
reusableComponentDevToolDetails.color = 'secondary-dark';
reusableComponentOptions.start = eventTime;
reusableComponentOptions.end =
reusableLaneDevToolDetails.color = 'secondary-dark';
reusableLaneOptions.start = eventTime;
reusableLaneOptions.end =
startTime > 0
? startTime
: updateTime > 0
? updateTime
: renderStartTime;
performance.measure(eventType, reusableComponentOptions);
performance.measure(eventType, reusableLaneOptions);
}
if (startTime > 0) {
// Log the time from when we started an async transition until we called setState or started rendering.
reusableComponentDevToolDetails.color = 'primary-dark';
reusableComponentOptions.start = startTime;
reusableComponentOptions.end =
updateTime > 0 ? updateTime : renderStartTime;
performance.measure('Action', reusableComponentOptions);
reusableLaneDevToolDetails.color = 'primary-dark';
reusableLaneOptions.start = startTime;
reusableLaneOptions.end = updateTime > 0 ? updateTime : renderStartTime;
performance.measure('Action', reusableLaneOptions);
}
if (updateTime > 0) {
// Log the time from when we called setState until we started rendering.
reusableComponentDevToolDetails.color = 'primary-light';
reusableComponentOptions.start = updateTime;
reusableComponentOptions.end = renderStartTime;
performance.measure('Blocked', reusableComponentOptions);
reusableLaneDevToolDetails.color = 'primary-light';
reusableLaneOptions.start = updateTime;
reusableLaneOptions.end = renderStartTime;
performance.measure('Blocked', reusableLaneOptions);
}
}
}

export function logRenderPhase(startTime: number, endTime: number): void {
if (supportsUserTiming) {
reusableComponentDevToolDetails.color = 'primary-dark';
reusableComponentOptions.start = startTime;
reusableComponentOptions.end = endTime;
performance.measure('Render', reusableComponentOptions);
reusableLaneDevToolDetails.color = 'primary-dark';
reusableLaneOptions.start = startTime;
reusableLaneOptions.end = endTime;
performance.measure('Render', reusableLaneOptions);
}
}

Expand All @@ -180,10 +192,10 @@ export function logSuspenseThrottlePhase(
): void {
// This was inside a throttled Suspense boundary commit.
if (supportsUserTiming) {
reusableComponentDevToolDetails.color = 'secondary-light';
reusableComponentOptions.start = startTime;
reusableComponentOptions.end = endTime;
performance.measure('Throttled', reusableComponentOptions);
reusableLaneDevToolDetails.color = 'secondary-light';
reusableLaneOptions.start = startTime;
reusableLaneOptions.end = endTime;
performance.measure('Throttled', reusableLaneOptions);
}
}

Expand All @@ -193,28 +205,28 @@ export function logSuspendedCommitPhase(
): void {
// This means the commit was suspended on CSS or images.
if (supportsUserTiming) {
reusableComponentDevToolDetails.color = 'secondary-light';
reusableComponentOptions.start = startTime;
reusableComponentOptions.end = endTime;
performance.measure('Suspended', reusableComponentOptions);
reusableLaneDevToolDetails.color = 'secondary-light';
reusableLaneOptions.start = startTime;
reusableLaneOptions.end = endTime;
performance.measure('Suspended', reusableLaneOptions);
}
}

export function logCommitPhase(startTime: number, endTime: number): void {
if (supportsUserTiming) {
reusableComponentDevToolDetails.color = 'secondary-dark';
reusableComponentOptions.start = startTime;
reusableComponentOptions.end = endTime;
performance.measure('Commit', reusableComponentOptions);
reusableLaneDevToolDetails.color = 'secondary-dark';
reusableLaneOptions.start = startTime;
reusableLaneOptions.end = endTime;
performance.measure('Commit', reusableLaneOptions);
}
}

export function logPaintYieldPhase(startTime: number, endTime: number): void {
if (supportsUserTiming) {
reusableComponentDevToolDetails.color = 'secondary-light';
reusableComponentOptions.start = startTime;
reusableComponentOptions.end = endTime;
performance.measure('Waiting for Paint', reusableComponentOptions);
reusableLaneDevToolDetails.color = 'secondary-light';
reusableLaneOptions.start = startTime;
reusableLaneOptions.end = endTime;
performance.measure('Waiting for Paint', reusableLaneOptions);
}
}

Expand All @@ -223,9 +235,9 @@ export function logPassiveCommitPhase(
endTime: number,
): void {
if (supportsUserTiming) {
reusableComponentDevToolDetails.color = 'secondary-dark';
reusableComponentOptions.start = startTime;
reusableComponentOptions.end = endTime;
performance.measure('Remaining Effects', reusableComponentOptions);
reusableLaneDevToolDetails.color = 'secondary-dark';
reusableLaneOptions.start = startTime;
reusableLaneOptions.end = endTime;
performance.measure('Remaining Effects', reusableLaneOptions);
}
}

0 comments on commit 8657869

Please sign in to comment.