Skip to content

Commit 6a4b46c

Browse files
authored
[Fiber] Log Effect and Render Times in Offscreen Commit Phase (facebook#31788)
In facebook#30967 and facebook#30983 I added logging of the just rendered components and the effects. However this didn't consider the special Offscreen passes. So this adds the same thing to those passes. Log component effect timings for disconnected/reconnected offscreen subtrees. This includes initial mount of a Suspense boundary. Log component render timings for reconnected and already offscreen offscreen subtrees.
1 parent facec3e commit 6a4b46c

File tree

2 files changed

+183
-16
lines changed

2 files changed

+183
-16
lines changed

packages/react-reconciler/src/ReactFiberCommitWork.js

Lines changed: 182 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2209,6 +2209,8 @@ function recursivelyTraverseLayoutEffects(
22092209
}
22102210

22112211
export function disappearLayoutEffects(finishedWork: Fiber) {
2212+
const prevEffectStart = pushComponentEffectStart();
2213+
22122214
switch (finishedWork.tag) {
22132215
case FunctionComponent:
22142216
case ForwardRef:
@@ -2266,6 +2268,25 @@ export function disappearLayoutEffects(finishedWork: Fiber) {
22662268
break;
22672269
}
22682270
}
2271+
2272+
if (
2273+
enableProfilerTimer &&
2274+
enableProfilerCommitHooks &&
2275+
enableComponentPerformanceTrack &&
2276+
(finishedWork.mode & ProfileMode) !== NoMode &&
2277+
componentEffectStartTime >= 0 &&
2278+
componentEffectEndTime >= 0 &&
2279+
componentEffectDuration > 0.05
2280+
) {
2281+
logComponentEffect(
2282+
finishedWork,
2283+
componentEffectStartTime,
2284+
componentEffectEndTime,
2285+
componentEffectDuration,
2286+
);
2287+
}
2288+
2289+
popComponentEffectStart(prevEffectStart);
22692290
}
22702291

22712292
function recursivelyTraverseDisappearLayoutEffects(parentFiber: Fiber) {
@@ -2286,6 +2307,8 @@ export function reappearLayoutEffects(
22862307
// node was reused.
22872308
includeWorkInProgressEffects: boolean,
22882309
) {
2310+
const prevEffectStart = pushComponentEffectStart();
2311+
22892312
// Turn on layout effects in a tree that previously disappeared.
22902313
const flags = finishedWork.flags;
22912314
switch (finishedWork.tag) {
@@ -2421,6 +2444,25 @@ export function reappearLayoutEffects(
24212444
break;
24222445
}
24232446
}
2447+
2448+
if (
2449+
enableProfilerTimer &&
2450+
enableProfilerCommitHooks &&
2451+
enableComponentPerformanceTrack &&
2452+
(finishedWork.mode & ProfileMode) !== NoMode &&
2453+
componentEffectStartTime >= 0 &&
2454+
componentEffectEndTime >= 0 &&
2455+
componentEffectDuration > 0.05
2456+
) {
2457+
logComponentEffect(
2458+
finishedWork,
2459+
componentEffectStartTime,
2460+
componentEffectEndTime,
2461+
componentEffectDuration,
2462+
);
2463+
}
2464+
2465+
popComponentEffectStart(prevEffectStart);
24242466
}
24252467

24262468
function recursivelyTraverseReappearLayoutEffects(
@@ -2846,6 +2888,7 @@ function commitPassiveMountOnFiber(
28462888
finishedWork,
28472889
committedLanes,
28482890
committedTransitions,
2891+
endTime,
28492892
);
28502893
} else {
28512894
// Legacy Mode: Fire the effects even if the tree is hidden.
@@ -2884,6 +2927,7 @@ function commitPassiveMountOnFiber(
28842927
committedLanes,
28852928
committedTransitions,
28862929
includeWorkInProgressEffects,
2930+
endTime,
28872931
);
28882932
}
28892933
}
@@ -2963,6 +3007,7 @@ function recursivelyTraverseReconnectPassiveEffects(
29633007
committedLanes: Lanes,
29643008
committedTransitions: Array<Transition> | null,
29653009
includeWorkInProgressEffects: boolean,
3010+
endTime: number,
29663011
) {
29673012
// This function visits both newly finished work and nodes that were re-used
29683013
// from a previously committed tree. We cannot check non-static flags if the
@@ -2974,14 +3019,30 @@ function recursivelyTraverseReconnectPassiveEffects(
29743019
// TODO (Offscreen) Check: flags & (RefStatic | LayoutStatic)
29753020
let child = parentFiber.child;
29763021
while (child !== null) {
2977-
reconnectPassiveEffects(
2978-
finishedRoot,
2979-
child,
2980-
committedLanes,
2981-
committedTransitions,
2982-
childShouldIncludeWorkInProgressEffects,
2983-
);
2984-
child = child.sibling;
3022+
if (enableProfilerTimer && enableComponentPerformanceTrack) {
3023+
const nextSibling = child.sibling;
3024+
reconnectPassiveEffects(
3025+
finishedRoot,
3026+
child,
3027+
committedLanes,
3028+
committedTransitions,
3029+
childShouldIncludeWorkInProgressEffects,
3030+
nextSibling !== null
3031+
? ((nextSibling.actualStartTime: any): number)
3032+
: endTime,
3033+
);
3034+
child = nextSibling;
3035+
} else {
3036+
reconnectPassiveEffects(
3037+
finishedRoot,
3038+
child,
3039+
committedLanes,
3040+
committedTransitions,
3041+
childShouldIncludeWorkInProgressEffects,
3042+
endTime,
3043+
);
3044+
child = child.sibling;
3045+
}
29853046
}
29863047
}
29873048

@@ -2994,7 +3055,28 @@ export function reconnectPassiveEffects(
29943055
// from a previously committed tree. We cannot check non-static flags if the
29953056
// node was reused.
29963057
includeWorkInProgressEffects: boolean,
3058+
endTime: number, // Profiling-only. The start time of the next Fiber or root completion.
29973059
) {
3060+
const prevEffectStart = pushComponentEffectStart();
3061+
3062+
// If this component rendered in Profiling mode (DEV or in Profiler component) then log its
3063+
// render time. We do this after the fact in the passive effect to avoid the overhead of this
3064+
// getting in the way of the render characteristics and avoid the overhead of unwinding
3065+
// uncommitted renders.
3066+
if (
3067+
enableProfilerTimer &&
3068+
enableComponentPerformanceTrack &&
3069+
(finishedWork.mode & ProfileMode) !== NoMode &&
3070+
((finishedWork.actualStartTime: any): number) > 0 &&
3071+
(finishedWork.flags & PerformedWork) !== NoFlags
3072+
) {
3073+
logComponentRender(
3074+
finishedWork,
3075+
((finishedWork.actualStartTime: any): number),
3076+
endTime,
3077+
);
3078+
}
3079+
29983080
const flags = finishedWork.flags;
29993081
switch (finishedWork.tag) {
30003082
case FunctionComponent:
@@ -3006,6 +3088,7 @@ export function reconnectPassiveEffects(
30063088
committedLanes,
30073089
committedTransitions,
30083090
includeWorkInProgressEffects,
3091+
endTime,
30093092
);
30103093
// TODO: Check for PassiveStatic flag
30113094
commitHookPassiveMountEffects(finishedWork, HookPassive);
@@ -3025,6 +3108,7 @@ export function reconnectPassiveEffects(
30253108
committedLanes,
30263109
committedTransitions,
30273110
includeWorkInProgressEffects,
3111+
endTime,
30283112
);
30293113

30303114
if (includeWorkInProgressEffects && flags & Passive) {
@@ -3051,6 +3135,7 @@ export function reconnectPassiveEffects(
30513135
committedLanes,
30523136
committedTransitions,
30533137
includeWorkInProgressEffects,
3138+
endTime,
30543139
);
30553140
} else {
30563141
if (disableLegacyMode || finishedWork.mode & ConcurrentMode) {
@@ -3064,6 +3149,7 @@ export function reconnectPassiveEffects(
30643149
finishedWork,
30653150
committedLanes,
30663151
committedTransitions,
3152+
endTime,
30673153
);
30683154
} else {
30693155
// Legacy Mode: Fire the effects even if the tree is hidden.
@@ -3074,6 +3160,7 @@ export function reconnectPassiveEffects(
30743160
committedLanes,
30753161
committedTransitions,
30763162
includeWorkInProgressEffects,
3163+
endTime,
30773164
);
30783165
}
30793166
}
@@ -3093,6 +3180,7 @@ export function reconnectPassiveEffects(
30933180
committedLanes,
30943181
committedTransitions,
30953182
includeWorkInProgressEffects,
3183+
endTime,
30963184
);
30973185
}
30983186

@@ -3110,6 +3198,7 @@ export function reconnectPassiveEffects(
31103198
committedLanes,
31113199
committedTransitions,
31123200
includeWorkInProgressEffects,
3201+
endTime,
31133202
);
31143203
if (includeWorkInProgressEffects && flags & Passive) {
31153204
// TODO: Pass `current` as argument to this function
@@ -3126,6 +3215,7 @@ export function reconnectPassiveEffects(
31263215
committedLanes,
31273216
committedTransitions,
31283217
includeWorkInProgressEffects,
3218+
endTime,
31293219
);
31303220
if (includeWorkInProgressEffects && flags & Passive) {
31313221
commitTracingMarkerPassiveMountEffect(finishedWork);
@@ -3141,17 +3231,38 @@ export function reconnectPassiveEffects(
31413231
committedLanes,
31423232
committedTransitions,
31433233
includeWorkInProgressEffects,
3234+
endTime,
31443235
);
31453236
break;
31463237
}
31473238
}
3239+
3240+
if (
3241+
enableProfilerTimer &&
3242+
enableProfilerCommitHooks &&
3243+
enableComponentPerformanceTrack &&
3244+
(finishedWork.mode & ProfileMode) !== NoMode &&
3245+
componentEffectStartTime >= 0 &&
3246+
componentEffectEndTime >= 0 &&
3247+
componentEffectDuration > 0.05
3248+
) {
3249+
logComponentEffect(
3250+
finishedWork,
3251+
componentEffectStartTime,
3252+
componentEffectEndTime,
3253+
componentEffectDuration,
3254+
);
3255+
}
3256+
3257+
popComponentEffectStart(prevEffectStart);
31483258
}
31493259

31503260
function recursivelyTraverseAtomicPassiveEffects(
31513261
finishedRoot: FiberRoot,
31523262
parentFiber: Fiber,
31533263
committedLanes: Lanes,
31543264
committedTransitions: Array<Transition> | null,
3265+
endTime: number, // Profiling-only. The start time of the next Fiber or root completion.
31553266
) {
31563267
// "Atomic" effects are ones that need to fire on every commit, even during
31573268
// pre-rendering. We call this function when traversing a hidden tree whose
@@ -3160,13 +3271,28 @@ function recursivelyTraverseAtomicPassiveEffects(
31603271
if (parentFiber.subtreeFlags & PassiveMask) {
31613272
let child = parentFiber.child;
31623273
while (child !== null) {
3163-
commitAtomicPassiveEffects(
3164-
finishedRoot,
3165-
child,
3166-
committedLanes,
3167-
committedTransitions,
3168-
);
3169-
child = child.sibling;
3274+
if (enableProfilerTimer && enableComponentPerformanceTrack) {
3275+
const nextSibling = child.sibling;
3276+
commitAtomicPassiveEffects(
3277+
finishedRoot,
3278+
child,
3279+
committedLanes,
3280+
committedTransitions,
3281+
nextSibling !== null
3282+
? ((nextSibling.actualStartTime: any): number)
3283+
: endTime,
3284+
);
3285+
child = nextSibling;
3286+
} else {
3287+
commitAtomicPassiveEffects(
3288+
finishedRoot,
3289+
child,
3290+
committedLanes,
3291+
committedTransitions,
3292+
endTime,
3293+
);
3294+
child = child.sibling;
3295+
}
31703296
}
31713297
}
31723298
}
@@ -3176,7 +3302,24 @@ function commitAtomicPassiveEffects(
31763302
finishedWork: Fiber,
31773303
committedLanes: Lanes,
31783304
committedTransitions: Array<Transition> | null,
3305+
endTime: number, // Profiling-only. The start time of the next Fiber or root completion.
31793306
) {
3307+
// If this component rendered in Profiling mode (DEV or in Profiler component) then log its
3308+
// render time. A render can happen even if the subtree is offscreen.
3309+
if (
3310+
enableProfilerTimer &&
3311+
enableComponentPerformanceTrack &&
3312+
(finishedWork.mode & ProfileMode) !== NoMode &&
3313+
((finishedWork.actualStartTime: any): number) > 0 &&
3314+
(finishedWork.flags & PerformedWork) !== NoFlags
3315+
) {
3316+
logComponentRender(
3317+
finishedWork,
3318+
((finishedWork.actualStartTime: any): number),
3319+
endTime,
3320+
);
3321+
}
3322+
31803323
// "Atomic" effects are ones that need to fire on every commit, even during
31813324
// pre-rendering. We call this function when traversing a hidden tree whose
31823325
// regular effects are currently disconnected.
@@ -3188,6 +3331,7 @@ function commitAtomicPassiveEffects(
31883331
finishedWork,
31893332
committedLanes,
31903333
committedTransitions,
3334+
endTime,
31913335
);
31923336
if (flags & Passive) {
31933337
// TODO: Pass `current` as argument to this function
@@ -3203,6 +3347,7 @@ function commitAtomicPassiveEffects(
32033347
finishedWork,
32043348
committedLanes,
32053349
committedTransitions,
3350+
endTime,
32063351
);
32073352
if (flags & Passive) {
32083353
// TODO: Pass `current` as argument to this function
@@ -3217,6 +3362,7 @@ function commitAtomicPassiveEffects(
32173362
finishedWork,
32183363
committedLanes,
32193364
committedTransitions,
3365+
endTime,
32203366
);
32213367
break;
32223368
}
@@ -3591,6 +3737,8 @@ function commitPassiveUnmountInsideDeletedTreeOnFiber(
35913737
current: Fiber,
35923738
nearestMountedAncestor: Fiber | null,
35933739
): void {
3740+
const prevEffectStart = pushComponentEffectStart();
3741+
35943742
switch (current.tag) {
35953743
case FunctionComponent:
35963744
case ForwardRef:
@@ -3702,6 +3850,25 @@ function commitPassiveUnmountInsideDeletedTreeOnFiber(
37023850
break;
37033851
}
37043852
}
3853+
3854+
if (
3855+
enableProfilerTimer &&
3856+
enableProfilerCommitHooks &&
3857+
enableComponentPerformanceTrack &&
3858+
(current.mode & ProfileMode) !== NoMode &&
3859+
componentEffectStartTime >= 0 &&
3860+
componentEffectEndTime >= 0 &&
3861+
componentEffectDuration > 0.05
3862+
) {
3863+
logComponentEffect(
3864+
current,
3865+
componentEffectStartTime,
3866+
componentEffectEndTime,
3867+
componentEffectDuration,
3868+
);
3869+
}
3870+
3871+
popComponentEffectStart(prevEffectStart);
37053872
}
37063873

37073874
export function invokeLayoutEffectMountInDEV(fiber: Fiber): void {

packages/react-reconciler/src/ReactFiberWorkLoop.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4139,7 +4139,7 @@ function doubleInvokeEffectsOnFiber(
41394139
}
41404140
reappearLayoutEffects(root, fiber.alternate, fiber, false);
41414141
if (shouldDoubleInvokePassiveEffects) {
4142-
reconnectPassiveEffects(root, fiber, NoLanes, null, false);
4142+
reconnectPassiveEffects(root, fiber, NoLanes, null, false, 0);
41434143
}
41444144
} finally {
41454145
setIsStrictModeForDevtools(false);

0 commit comments

Comments
 (0)