Skip to content

Commit d2b6779

Browse files
committed
Log the previously rendered component as a deduped entry
1 parent 1f6a108 commit d2b6779

File tree

3 files changed

+60
-6
lines changed

3 files changed

+60
-6
lines changed

fixtures/flight/src/App.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ function Foo({children}) {
2727
return <div>{children}</div>;
2828
}
2929

30-
function Bar({children}) {
30+
async function Bar({children}) {
31+
await new Promise(resolve => setTimeout(() => resolve('deferred text'), 10));
3132
return <div>{children}</div>;
3233
}
3334

@@ -81,7 +82,7 @@ export default async function App({prerender}) {
8182
<Client />
8283
<Note />
8384
<Foo>{dedupedChild}</Foo>
84-
<Bar>{dedupedChild}</Bar>
85+
<Bar>{Promise.resolve([dedupedChild])}</Bar>
8586
</Container>
8687
</body>
8788
</html>

packages/react-client/src/ReactFlightClient.js

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ import {readTemporaryReference} from './ReactFlightTemporaryReferences';
7474
import {
7575
markAllTracksInOrder,
7676
logComponentRender,
77+
logDedupedComponentRender,
7778
} from './ReactFlightPerformanceTrack';
7879

7980
import {
@@ -132,6 +133,7 @@ export type JSONValue =
132133
type ProfilingResult = {
133134
track: number,
134135
endTime: number,
136+
component: null | ReactComponentInfo,
135137
};
136138

137139
const ROW_ID = 0;
@@ -653,7 +655,7 @@ export function reportGlobalError(response: Response, error: Error): void {
653655
});
654656
if (enableProfilerTimer && enableComponentPerformanceTrack) {
655657
markAllTracksInOrder();
656-
flushComponentPerformance(getChunk(response, 0), 0, -Infinity);
658+
flushComponentPerformance(getChunk(response, 0), 0, -Infinity, -Infinity);
657659
}
658660
}
659661

@@ -2761,7 +2763,8 @@ function resolveTypedArray(
27612763
function flushComponentPerformance(
27622764
root: SomeChunk<any>,
27632765
trackIdx: number, // Next available track
2764-
trackTime: number, // The time after which it is available
2766+
trackTime: number, // The time after which it is available,
2767+
parentEndTime: number,
27652768
): ProfilingResult {
27662769
if (!enableProfilerTimer || !enableComponentPerformanceTrack) {
27672770
// eslint-disable-next-line react-internal/prod-error-codes
@@ -2778,6 +2781,22 @@ function flushComponentPerformance(
27782781
// chunk in two places. We should extend the current end time as if it was
27792782
// rendered as part of this tree.
27802783
const previousResult: ProfilingResult = root._children;
2784+
const previousEndTime = previousResult.endTime;
2785+
if (
2786+
parentEndTime > -Infinity &&
2787+
parentEndTime < previousEndTime &&
2788+
previousResult.component !== null
2789+
) {
2790+
// Log a placeholder for the deduped value under this child starting
2791+
// from the end of the self time of the parent and spanning until the
2792+
// the deduped end.
2793+
logDedupedComponentRender(
2794+
previousResult.component,
2795+
trackIdx,
2796+
parentEndTime,
2797+
previousEndTime,
2798+
);
2799+
}
27812800
// Since we didn't bump the track this time, we just return the same track.
27822801
previousResult.track = trackIdx;
27832802
return previousResult;
@@ -2805,15 +2824,27 @@ function flushComponentPerformance(
28052824
// The start time of this component is before the end time of the previous
28062825
// component on this track so we need to bump the next one to a parallel track.
28072826
trackIdx++;
2808-
trackTime = startTime;
28092827
}
2828+
trackTime = startTime;
28102829
break;
28112830
}
28122831
}
28132832
}
2833+
for (let i = debugInfo.length - 1; i >= 0; i--) {
2834+
const info = debugInfo[i];
2835+
if (typeof info.time === 'number') {
2836+
if (info.time > parentEndTime) {
2837+
parentEndTime = info.time;
2838+
}
2839+
}
2840+
}
28142841
}
28152842

2816-
const result: ProfilingResult = {track: trackIdx, endTime: -Infinity};
2843+
const result: ProfilingResult = {
2844+
track: trackIdx,
2845+
endTime: -Infinity,
2846+
component: null,
2847+
};
28172848
root._children = result;
28182849
let childrenEndTime = -Infinity;
28192850
let childTrackIdx = trackIdx;
@@ -2823,7 +2854,11 @@ function flushComponentPerformance(
28232854
children[i],
28242855
childTrackIdx,
28252856
childTrackTime,
2857+
parentEndTime,
28262858
);
2859+
if (childResult.component !== null) {
2860+
result.component = childResult.component;
2861+
}
28272862
childTrackIdx = childResult.track;
28282863
const childEndTime = childResult.endTime;
28292864
childTrackTime = childEndTime;
@@ -2855,6 +2890,8 @@ function flushComponentPerformance(
28552890
endTime,
28562891
childrenEndTime,
28572892
);
2893+
// Track the root most component of the result for deduping logging.
2894+
result.component = componentInfo;
28582895
}
28592896
}
28602897
}

packages/react-client/src/ReactFlightPerformanceTrack.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,3 +90,19 @@ export function logComponentRender(
9090
performance.measure(name, reusableComponentOptions);
9191
}
9292
}
93+
94+
export function logDedupedComponentRender(
95+
componentInfo: ReactComponentInfo,
96+
trackIdx: number,
97+
startTime: number,
98+
endTime: number,
99+
): void {
100+
if (supportsUserTiming && endTime >= 0 && trackIdx < 10) {
101+
const name = componentInfo.name;
102+
reusableComponentDevToolDetails.color = 'tertiary-light';
103+
reusableComponentDevToolDetails.track = trackNames[trackIdx];
104+
reusableComponentOptions.start = startTime < 0 ? 0 : startTime;
105+
reusableComponentOptions.end = endTime;
106+
performance.measure(name + ' [deduped]', reusableComponentOptions);
107+
}
108+
}

0 commit comments

Comments
 (0)