Skip to content

Commit

Permalink
[Flight] Emit Deduped Server Components Marker (#31737)
Browse files Browse the repository at this point in the history
Stacked on #31736.

<img width="1223" alt="Screenshot 2024-12-11 at 8 21 12 PM"
src="https://github.com/user-attachments/assets/a7cbc04b-c831-476b-aa2f-baddec9461c9"
/>

This emits a placeholder when we're deduping a component. This starts
when the parent's self time ends, where we would've started rendering
this component if it wasn't already started. The end time is when the
actual render ends since the parent is also blocked by it.
  • Loading branch information
sebmarkbage authored Dec 16, 2024
1 parent 07facb5 commit bdf1871
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 6 deletions.
5 changes: 3 additions & 2 deletions fixtures/flight/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ function Foo({children}) {
return <div>{children}</div>;
}

function Bar({children}) {
async function Bar({children}) {
await new Promise(resolve => setTimeout(() => resolve('deferred text'), 10));
return <div>{children}</div>;
}

Expand Down Expand Up @@ -81,7 +82,7 @@ export default async function App({prerender}) {
<Client />
<Note />
<Foo>{dedupedChild}</Foo>
<Bar>{dedupedChild}</Bar>
<Bar>{Promise.resolve([dedupedChild])}</Bar>
</Container>
</body>
</html>
Expand Down
45 changes: 41 additions & 4 deletions packages/react-client/src/ReactFlightClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ import {readTemporaryReference} from './ReactFlightTemporaryReferences';
import {
markAllTracksInOrder,
logComponentRender,
logDedupedComponentRender,
} from './ReactFlightPerformanceTrack';

import {
Expand Down Expand Up @@ -130,6 +131,7 @@ export type JSONValue =
type ProfilingResult = {
track: number,
endTime: number,
component: null | ReactComponentInfo,
};

const ROW_ID = 0;
Expand Down Expand Up @@ -647,7 +649,7 @@ export function reportGlobalError(response: Response, error: Error): void {
});
if (enableProfilerTimer && enableComponentPerformanceTrack) {
markAllTracksInOrder();
flushComponentPerformance(getChunk(response, 0), 0, -Infinity);
flushComponentPerformance(getChunk(response, 0), 0, -Infinity, -Infinity);
}
}

Expand Down Expand Up @@ -2748,7 +2750,8 @@ function resolveTypedArray(
function flushComponentPerformance(
root: SomeChunk<any>,
trackIdx: number, // Next available track
trackTime: number, // The time after which it is available
trackTime: number, // The time after which it is available,
parentEndTime: number,
): ProfilingResult {
if (!enableProfilerTimer || !enableComponentPerformanceTrack) {
// eslint-disable-next-line react-internal/prod-error-codes
Expand All @@ -2765,6 +2768,22 @@ function flushComponentPerformance(
// chunk in two places. We should extend the current end time as if it was
// rendered as part of this tree.
const previousResult: ProfilingResult = root._children;
const previousEndTime = previousResult.endTime;
if (
parentEndTime > -Infinity &&
parentEndTime < previousEndTime &&
previousResult.component !== null
) {
// Log a placeholder for the deduped value under this child starting
// from the end of the self time of the parent and spanning until the
// the deduped end.
logDedupedComponentRender(
previousResult.component,
trackIdx,
parentEndTime,
previousEndTime,
);
}
// Since we didn't bump the track this time, we just return the same track.
previousResult.track = trackIdx;
return previousResult;
Expand Down Expand Up @@ -2792,15 +2811,27 @@ function flushComponentPerformance(
// The start time of this component is before the end time of the previous
// component on this track so we need to bump the next one to a parallel track.
trackIdx++;
trackTime = startTime;
}
trackTime = startTime;
break;
}
}
}
for (let i = debugInfo.length - 1; i >= 0; i--) {
const info = debugInfo[i];
if (typeof info.time === 'number') {
if (info.time > parentEndTime) {
parentEndTime = info.time;
}
}
}
}

const result: ProfilingResult = {track: trackIdx, endTime: -Infinity};
const result: ProfilingResult = {
track: trackIdx,
endTime: -Infinity,
component: null,
};
root._children = result;
let childrenEndTime = -Infinity;
let childTrackIdx = trackIdx;
Expand All @@ -2810,7 +2841,11 @@ function flushComponentPerformance(
children[i],
childTrackIdx,
childTrackTime,
parentEndTime,
);
if (childResult.component !== null) {
result.component = childResult.component;
}
childTrackIdx = childResult.track;
const childEndTime = childResult.endTime;
childTrackTime = childEndTime;
Expand Down Expand Up @@ -2842,6 +2877,8 @@ function flushComponentPerformance(
endTime,
childrenEndTime,
);
// Track the root most component of the result for deduping logging.
result.component = componentInfo;
}
}
}
Expand Down
16 changes: 16 additions & 0 deletions packages/react-client/src/ReactFlightPerformanceTrack.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,19 @@ export function logComponentRender(
performance.measure(name, reusableComponentOptions);
}
}

export function logDedupedComponentRender(
componentInfo: ReactComponentInfo,
trackIdx: number,
startTime: number,
endTime: number,
): void {
if (supportsUserTiming && endTime >= 0 && trackIdx < 10) {
const name = componentInfo.name;
reusableComponentDevToolDetails.color = 'tertiary-light';
reusableComponentDevToolDetails.track = trackNames[trackIdx];
reusableComponentOptions.start = startTime < 0 ? 0 : startTime;
reusableComponentOptions.end = endTime;
performance.measure(name + ' [deduped]', reusableComponentOptions);
}
}

0 comments on commit bdf1871

Please sign in to comment.