Skip to content

Commit ee1a403

Browse files
authored
[Fiber] Move Profiler onPostCommit processing of passive effect durations to plain passive effect (#30966)
We used to queue a separate third passive phase to invoke onPostCommit but this is unnecessary. We can just treat it as a plain passive effect. This means it is interleaved with other passive effects but we only need to know the duration of the things below us which is already done at this point. I also extracted the user space call to onPostCommit into ReactCommitEffects. Same as onCommit. It's now covered by runWithFiberInDEV and catches.
1 parent 0eab377 commit ee1a403

File tree

4 files changed

+106
-96
lines changed

4 files changed

+106
-96
lines changed

packages/react-reconciler/src/ReactFiberBeginWork.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1026,6 +1026,10 @@ function updateProfiler(
10261026
workInProgress.flags |= Update;
10271027

10281028
if (enableProfilerCommitHooks) {
1029+
// Schedule a passive effect for this Profiler to call onPostCommit hooks.
1030+
// This effect should be scheduled even if there is no onPostCommit callback for this Profiler,
1031+
// because the effect is also where times bubble to parent Profilers.
1032+
workInProgress.flags |= Passive;
10291033
// Reset effect durations for the next eventual effect phase.
10301034
// These are reset during render to allow the DevTools commit hook a chance to read them,
10311035
const stateNode = workInProgress.stateNode;
@@ -3700,6 +3704,10 @@ function attemptEarlyBailoutIfNoScheduledUpdate(
37003704
}
37013705

37023706
if (enableProfilerCommitHooks) {
3707+
// Schedule a passive effect for this Profiler to call onPostCommit hooks.
3708+
// This effect should be scheduled even if there is no onPostCommit callback for this Profiler,
3709+
// because the effect is also where times bubble to parent Profilers.
3710+
workInProgress.flags |= Passive;
37033711
// Reset effect durations for the next eventual effect phase.
37043712
// These are reset during render to allow the DevTools commit hook a chance to read them,
37053713
const stateNode = workInProgress.stateNode;

packages/react-reconciler/src/ReactFiberCommitEffects.js

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -881,7 +881,7 @@ function commitProfiler(
881881
commitTime: number,
882882
effectDuration: number,
883883
) {
884-
const {onCommit, onRender} = finishedWork.memoizedProps;
884+
const {id, onCommit, onRender} = finishedWork.memoizedProps;
885885

886886
let phase = current === null ? 'mount' : 'update';
887887
if (enableProfilerNestedUpdatePhase) {
@@ -892,7 +892,7 @@ function commitProfiler(
892892

893893
if (typeof onRender === 'function') {
894894
onRender(
895-
finishedWork.memoizedProps.id,
895+
id,
896896
phase,
897897
finishedWork.actualDuration,
898898
finishedWork.treeBaseDuration,
@@ -938,3 +938,52 @@ export function commitProfilerUpdate(
938938
}
939939
}
940940
}
941+
942+
function commitProfilerPostCommitImpl(
943+
finishedWork: Fiber,
944+
current: Fiber | null,
945+
commitTime: number,
946+
passiveEffectDuration: number,
947+
): void {
948+
const {id, onPostCommit} = finishedWork.memoizedProps;
949+
950+
let phase = current === null ? 'mount' : 'update';
951+
if (enableProfilerNestedUpdatePhase) {
952+
if (isCurrentUpdateNested()) {
953+
phase = 'nested-update';
954+
}
955+
}
956+
957+
if (typeof onPostCommit === 'function') {
958+
onPostCommit(id, phase, passiveEffectDuration, commitTime);
959+
}
960+
}
961+
962+
export function commitProfilerPostCommit(
963+
finishedWork: Fiber,
964+
current: Fiber | null,
965+
commitTime: number,
966+
passiveEffectDuration: number,
967+
) {
968+
try {
969+
if (__DEV__) {
970+
runWithFiberInDEV(
971+
finishedWork,
972+
commitProfilerPostCommitImpl,
973+
finishedWork,
974+
current,
975+
commitTime,
976+
passiveEffectDuration,
977+
);
978+
} else {
979+
commitProfilerPostCommitImpl(
980+
finishedWork,
981+
current,
982+
commitTime,
983+
passiveEffectDuration,
984+
);
985+
}
986+
} catch (error) {
987+
captureCommitPhaseError(finishedWork, finishedWork.return, error);
988+
}
989+
}

packages/react-reconciler/src/ReactFiberCommitWork.js

Lines changed: 47 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ import {
4444
enablePersistedModeClonedFlag,
4545
enableProfilerTimer,
4646
enableProfilerCommitHooks,
47-
enableProfilerNestedUpdatePhase,
4847
enableSchedulingProfiler,
4948
enableSuspenseCallback,
5049
enableScopeAPI,
@@ -100,7 +99,6 @@ import {
10099
Cloned,
101100
} from './ReactFiberFlags';
102101
import {
103-
isCurrentUpdateNested,
104102
getCommitTime,
105103
recordLayoutEffectDuration,
106104
startLayoutEffectTimer,
@@ -137,7 +135,6 @@ import {
137135
captureCommitPhaseError,
138136
resolveRetryWakeable,
139137
markCommitTimeOfFallback,
140-
enqueuePendingPassiveProfilerEffect,
141138
restorePendingUpdaters,
142139
addTransitionStartCallbackToPendingTransition,
143140
addTransitionProgressCallbackToPendingTransition,
@@ -193,6 +190,7 @@ import {
193190
safelyDetachRef,
194191
safelyCallDestroy,
195192
commitProfilerUpdate,
193+
commitProfilerPostCommit,
196194
commitRootCallbacks,
197195
} from './ReactFiberCommitEffects';
198196
import {
@@ -394,62 +392,6 @@ function commitBeforeMutationEffectsDeletion(deletion: Fiber) {
394392
}
395393
}
396394

397-
export function commitPassiveEffectDurations(
398-
finishedRoot: FiberRoot,
399-
finishedWork: Fiber,
400-
): void {
401-
if (
402-
enableProfilerTimer &&
403-
enableProfilerCommitHooks &&
404-
getExecutionContext() & CommitContext
405-
) {
406-
// Only Profilers with work in their subtree will have an Update effect scheduled.
407-
if ((finishedWork.flags & Update) !== NoFlags) {
408-
switch (finishedWork.tag) {
409-
case Profiler: {
410-
const {passiveEffectDuration} = finishedWork.stateNode;
411-
const {id, onPostCommit} = finishedWork.memoizedProps;
412-
413-
// This value will still reflect the previous commit phase.
414-
// It does not get reset until the start of the next commit phase.
415-
const commitTime = getCommitTime();
416-
417-
let phase = finishedWork.alternate === null ? 'mount' : 'update';
418-
if (enableProfilerNestedUpdatePhase) {
419-
if (isCurrentUpdateNested()) {
420-
phase = 'nested-update';
421-
}
422-
}
423-
424-
if (typeof onPostCommit === 'function') {
425-
onPostCommit(id, phase, passiveEffectDuration, commitTime);
426-
}
427-
428-
// Bubble times to the next nearest ancestor Profiler.
429-
// After we process that Profiler, we'll bubble further up.
430-
let parentFiber = finishedWork.return;
431-
outer: while (parentFiber !== null) {
432-
switch (parentFiber.tag) {
433-
case HostRoot:
434-
const root = parentFiber.stateNode;
435-
root.passiveEffectDuration += passiveEffectDuration;
436-
break outer;
437-
case Profiler:
438-
const parentStateNode = parentFiber.stateNode;
439-
parentStateNode.passiveEffectDuration += passiveEffectDuration;
440-
break outer;
441-
}
442-
parentFiber = parentFiber.return;
443-
}
444-
break;
445-
}
446-
default:
447-
break;
448-
}
449-
}
450-
}
451-
}
452-
453395
function commitLayoutEffectOnFiber(
454396
finishedRoot: FiberRoot,
455397
current: Fiber | null,
@@ -557,11 +499,6 @@ function commitLayoutEffectOnFiber(
557499
effectDuration,
558500
);
559501

560-
// Schedule a passive effect for this Profiler to call onPostCommit hooks.
561-
// This effect should be scheduled even if there is no onPostCommit callback for this Profiler,
562-
// because the effect is also where times bubble to parent Profilers.
563-
enqueuePendingPassiveProfilerEffect(finishedWork);
564-
565502
// Propagate layout effect durations to the next nearest Profiler ancestor.
566503
// Do not reset these values until the next render so DevTools has a chance to read them first.
567504
let parentFiber = finishedWork.return;
@@ -2475,11 +2412,6 @@ export function reappearLayoutEffects(
24752412
effectDuration,
24762413
);
24772414

2478-
// Schedule a passive effect for this Profiler to call onPostCommit hooks.
2479-
// This effect should be scheduled even if there is no onPostCommit callback for this Profiler,
2480-
// because the effect is also where times bubble to parent Profilers.
2481-
enqueuePendingPassiveProfilerEffect(finishedWork);
2482-
24832415
// Propagate layout effect durations to the next nearest Profiler ancestor.
24842416
// Do not reset these values until the next render so DevTools has a chance to read them first.
24852417
let parentFiber = finishedWork.return;
@@ -2824,6 +2756,52 @@ function commitPassiveMountOnFiber(
28242756
}
28252757
break;
28262758
}
2759+
case Profiler: {
2760+
recursivelyTraversePassiveMountEffects(
2761+
finishedRoot,
2762+
finishedWork,
2763+
committedLanes,
2764+
committedTransitions,
2765+
);
2766+
2767+
// Only Profilers with work in their subtree will have a Passive effect scheduled.
2768+
if (flags & Passive) {
2769+
if (
2770+
enableProfilerTimer &&
2771+
enableProfilerCommitHooks &&
2772+
getExecutionContext() & CommitContext
2773+
) {
2774+
const {passiveEffectDuration} = finishedWork.stateNode;
2775+
2776+
commitProfilerPostCommit(
2777+
finishedWork,
2778+
finishedWork.alternate,
2779+
// This value will still reflect the previous commit phase.
2780+
// It does not get reset until the start of the next commit phase.
2781+
getCommitTime(),
2782+
passiveEffectDuration,
2783+
);
2784+
2785+
// Bubble times to the next nearest ancestor Profiler.
2786+
// After we process that Profiler, we'll bubble further up.
2787+
let parentFiber = finishedWork.return;
2788+
outer: while (parentFiber !== null) {
2789+
switch (parentFiber.tag) {
2790+
case HostRoot:
2791+
const root = parentFiber.stateNode;
2792+
root.passiveEffectDuration += passiveEffectDuration;
2793+
break outer;
2794+
case Profiler:
2795+
const parentStateNode = parentFiber.stateNode;
2796+
parentStateNode.passiveEffectDuration += passiveEffectDuration;
2797+
break outer;
2798+
}
2799+
parentFiber = parentFiber.return;
2800+
}
2801+
}
2802+
}
2803+
break;
2804+
}
28272805
case LegacyHiddenComponent: {
28282806
if (enableLegacyHidden) {
28292807
recursivelyTraversePassiveMountEffects(

packages/react-reconciler/src/ReactFiberWorkLoop.js

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,6 @@ import {
189189
commitBeforeMutationEffects,
190190
commitLayoutEffects,
191191
commitMutationEffects,
192-
commitPassiveEffectDurations,
193192
commitPassiveMountEffects,
194193
commitPassiveUnmountEffects,
195194
disappearLayoutEffects,
@@ -580,7 +579,6 @@ let legacyErrorBoundariesThatAlreadyFailed: Set<mixed> | null = null;
580579
let rootDoesHavePassiveEffects: boolean = false;
581580
let rootWithPendingPassiveEffects: FiberRoot | null = null;
582581
let pendingPassiveEffectsLanes: Lanes = NoLanes;
583-
let pendingPassiveProfilerEffects: Array<Fiber> = [];
584582
let pendingPassiveEffectsRemainingLanes: Lanes = NoLanes;
585583
let pendingPassiveTransitions: Array<Transition> | null = null;
586584

@@ -3475,19 +3473,6 @@ export function flushPassiveEffects(): boolean {
34753473
return false;
34763474
}
34773475

3478-
export function enqueuePendingPassiveProfilerEffect(fiber: Fiber): void {
3479-
if (enableProfilerTimer && enableProfilerCommitHooks) {
3480-
pendingPassiveProfilerEffects.push(fiber);
3481-
if (!rootDoesHavePassiveEffects) {
3482-
rootDoesHavePassiveEffects = true;
3483-
scheduleCallback(NormalSchedulerPriority, () => {
3484-
flushPassiveEffects();
3485-
return null;
3486-
});
3487-
}
3488-
}
3489-
}
3490-
34913476
function flushPassiveEffectsImpl() {
34923477
if (rootWithPendingPassiveEffects === null) {
34933478
return false;
@@ -3528,16 +3513,6 @@ function flushPassiveEffectsImpl() {
35283513
commitPassiveUnmountEffects(root.current);
35293514
commitPassiveMountEffects(root, root.current, lanes, transitions);
35303515

3531-
// TODO: Move to commitPassiveMountEffects
3532-
if (enableProfilerTimer && enableProfilerCommitHooks) {
3533-
const profilerEffects = pendingPassiveProfilerEffects;
3534-
pendingPassiveProfilerEffects = [];
3535-
for (let i = 0; i < profilerEffects.length; i++) {
3536-
const fiber = ((profilerEffects[i]: any): Fiber);
3537-
commitPassiveEffectDurations(root, fiber);
3538-
}
3539-
}
3540-
35413516
if (__DEV__) {
35423517
if (enableDebugTracing) {
35433518
logPassiveEffectsStopped();

0 commit comments

Comments
 (0)