Skip to content

Commit a30a1c6

Browse files
authored
Transfer actualDuration only once for SuspenseList (facebook#18959)
1 parent 8b3b5c3 commit a30a1c6

9 files changed

+271
-26
lines changed

packages/react-reconciler/src/ReactFiberCompleteWork.new.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ import {
5858
OffscreenComponent,
5959
LegacyHiddenComponent,
6060
} from './ReactWorkTags';
61-
import {NoMode, BlockingMode} from './ReactTypeOfMode';
61+
import {NoMode, BlockingMode, ProfileMode} from './ReactTypeOfMode';
6262
import {
6363
Ref,
6464
Update,
@@ -128,6 +128,7 @@ import {
128128
enableFundamentalAPI,
129129
enableScopeAPI,
130130
enableBlocksAPI,
131+
enableProfilerTimer,
131132
} from 'shared/ReactFeatureFlags';
132133
import {
133134
markSpawnedWork,
@@ -141,6 +142,7 @@ import {OffscreenLane} from './ReactFiberLane';
141142
import {resetChildFibers} from './ReactChildFiber.new';
142143
import {updateDeprecatedEventListeners} from './ReactFiberDeprecatedEvents.new';
143144
import {createScopeInstance} from './ReactFiberScope.new';
145+
import {transferActualDuration} from './ReactProfilerTimer.new';
144146

145147
function markUpdate(workInProgress: Fiber) {
146148
// Tag the fiber with an update effect. This turns a Placement into
@@ -890,6 +892,12 @@ function completeWork(
890892
// Something suspended. Re-render with the fallback children.
891893
workInProgress.lanes = renderLanes;
892894
// Do not reset the effect list.
895+
if (
896+
enableProfilerTimer &&
897+
(workInProgress.mode & ProfileMode) !== NoMode
898+
) {
899+
transferActualDuration(workInProgress);
900+
}
893901
return workInProgress;
894902
}
895903

packages/react-reconciler/src/ReactFiberCompleteWork.old.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ import {
5454
ScopeComponent,
5555
Block,
5656
} from './ReactWorkTags';
57-
import {NoMode, BlockingMode} from './ReactTypeOfMode';
57+
import {NoMode, BlockingMode, ProfileMode} from './ReactTypeOfMode';
5858
import {
5959
Ref,
6060
Update,
@@ -125,6 +125,7 @@ import {
125125
enableFundamentalAPI,
126126
enableScopeAPI,
127127
enableBlocksAPI,
128+
enableProfilerTimer,
128129
} from 'shared/ReactFeatureFlags';
129130
import {
130131
markSpawnedWork,
@@ -137,6 +138,7 @@ import {Never} from './ReactFiberExpirationTime.old';
137138
import {resetChildFibers} from './ReactChildFiber.old';
138139
import {updateDeprecatedEventListeners} from './ReactFiberDeprecatedEvents.old';
139140
import {createScopeInstance} from './ReactFiberScope.old';
141+
import {transferActualDuration} from './ReactProfilerTimer.old';
140142

141143
function markUpdate(workInProgress: Fiber) {
142144
// Tag the fiber with an update effect. This turns a Placement into
@@ -885,6 +887,12 @@ function completeWork(
885887
if ((workInProgress.effectTag & DidCapture) !== NoEffect) {
886888
// Something suspended. Re-render with the fallback children.
887889
workInProgress.expirationTime = renderExpirationTime;
890+
if (
891+
enableProfilerTimer &&
892+
(workInProgress.mode & ProfileMode) !== NoMode
893+
) {
894+
transferActualDuration(workInProgress);
895+
}
888896
// Do not reset the effect list.
889897
return workInProgress;
890898
}
@@ -1084,6 +1092,7 @@ function completeWork(
10841092
ForceSuspenseFallback,
10851093
),
10861094
);
1095+
10871096
return workInProgress.child;
10881097
}
10891098
row = row.sibling;

packages/react-reconciler/src/ReactFiberUnwindWork.new.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,11 @@ import {
2424
LegacyHiddenComponent,
2525
} from './ReactWorkTags';
2626
import {DidCapture, NoEffect, ShouldCapture} from './ReactSideEffectTags';
27-
import {enableSuspenseServerRenderer} from 'shared/ReactFeatureFlags';
27+
import {NoMode, ProfileMode} from './ReactTypeOfMode';
28+
import {
29+
enableSuspenseServerRenderer,
30+
enableProfilerTimer,
31+
} from 'shared/ReactFeatureFlags';
2832

2933
import {popHostContainer, popHostContext} from './ReactFiberHostContext.new';
3034
import {popSuspenseContext} from './ReactFiberSuspenseContext.new';
@@ -36,6 +40,7 @@ import {
3640
} from './ReactFiberContext.new';
3741
import {popProvider} from './ReactFiberNewContext.new';
3842
import {popRenderLanes} from './ReactFiberWorkLoop.new';
43+
import {transferActualDuration} from './ReactProfilerTimer.new';
3944

4045
import invariant from 'shared/invariant';
4146

@@ -49,6 +54,12 @@ function unwindWork(workInProgress: Fiber, renderLanes: Lanes) {
4954
const effectTag = workInProgress.effectTag;
5055
if (effectTag & ShouldCapture) {
5156
workInProgress.effectTag = (effectTag & ~ShouldCapture) | DidCapture;
57+
if (
58+
enableProfilerTimer &&
59+
(workInProgress.mode & ProfileMode) !== NoMode
60+
) {
61+
transferActualDuration(workInProgress);
62+
}
5263
return workInProgress;
5364
}
5465
return null;
@@ -89,6 +100,12 @@ function unwindWork(workInProgress: Fiber, renderLanes: Lanes) {
89100
if (effectTag & ShouldCapture) {
90101
workInProgress.effectTag = (effectTag & ~ShouldCapture) | DidCapture;
91102
// Captured a suspense effect. Re-render the boundary.
103+
if (
104+
enableProfilerTimer &&
105+
(workInProgress.mode & ProfileMode) !== NoMode
106+
) {
107+
transferActualDuration(workInProgress);
108+
}
92109
return workInProgress;
93110
}
94111
return null;

packages/react-reconciler/src/ReactFiberUnwindWork.old.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,11 @@ import {
2222
SuspenseListComponent,
2323
} from './ReactWorkTags';
2424
import {DidCapture, NoEffect, ShouldCapture} from './ReactSideEffectTags';
25-
import {enableSuspenseServerRenderer} from 'shared/ReactFeatureFlags';
25+
import {NoMode, ProfileMode} from './ReactTypeOfMode';
26+
import {
27+
enableSuspenseServerRenderer,
28+
enableProfilerTimer,
29+
} from 'shared/ReactFeatureFlags';
2630

2731
import {popHostContainer, popHostContext} from './ReactFiberHostContext.old';
2832
import {popSuspenseContext} from './ReactFiberSuspenseContext.old';
@@ -33,6 +37,7 @@ import {
3337
popTopLevelContextObject as popTopLevelLegacyContextObject,
3438
} from './ReactFiberContext.old';
3539
import {popProvider} from './ReactFiberNewContext.old';
40+
import {transferActualDuration} from './ReactProfilerTimer.old';
3641

3742
import invariant from 'shared/invariant';
3843

@@ -49,6 +54,12 @@ function unwindWork(
4954
const effectTag = workInProgress.effectTag;
5055
if (effectTag & ShouldCapture) {
5156
workInProgress.effectTag = (effectTag & ~ShouldCapture) | DidCapture;
57+
if (
58+
enableProfilerTimer &&
59+
(workInProgress.mode & ProfileMode) !== NoMode
60+
) {
61+
transferActualDuration(workInProgress);
62+
}
5263
return workInProgress;
5364
}
5465
return null;
@@ -89,6 +100,12 @@ function unwindWork(
89100
if (effectTag & ShouldCapture) {
90101
workInProgress.effectTag = (effectTag & ~ShouldCapture) | DidCapture;
91102
// Captured a suspense effect. Re-render the boundary.
103+
if (
104+
enableProfilerTimer &&
105+
(workInProgress.mode & ProfileMode) !== NoMode
106+
) {
107+
transferActualDuration(workInProgress);
108+
}
92109
return workInProgress;
93110
}
94111
return null;

packages/react-reconciler/src/ReactFiberWorkLoop.new.js

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1571,14 +1571,15 @@ function completeUnitOfWork(unitOfWork: Fiber): void {
15711571
stopProfilerTimerIfRunningAndRecordDelta(completedWork, false);
15721572
}
15731573
resetCurrentDebugFiberInDEV();
1574-
resetChildLanes(completedWork);
15751574

15761575
if (next !== null) {
15771576
// Completing this fiber spawned new work. Work on that next.
15781577
workInProgress = next;
15791578
return;
15801579
}
15811580

1581+
resetChildLanes(completedWork);
1582+
15821583
if (
15831584
returnFiber !== null &&
15841585
// Do not append effects to parents if a sibling failed to complete
@@ -1625,6 +1626,16 @@ function completeUnitOfWork(unitOfWork: Fiber): void {
16251626

16261627
// Because this fiber did not complete, don't reset its expiration time.
16271628

1629+
if (next !== null) {
1630+
// If completing this work spawned new work, do that next. We'll come
1631+
// back here again.
1632+
// Since we're restarting, remove anything that is not a host effect
1633+
// from the effect tag.
1634+
next.effectTag &= HostEffectMask;
1635+
workInProgress = next;
1636+
return;
1637+
}
1638+
16281639
if (
16291640
enableProfilerTimer &&
16301641
(completedWork.mode & ProfileMode) !== NoMode
@@ -1642,16 +1653,6 @@ function completeUnitOfWork(unitOfWork: Fiber): void {
16421653
completedWork.actualDuration = actualDuration;
16431654
}
16441655

1645-
if (next !== null) {
1646-
// If completing this work spawned new work, do that next. We'll come
1647-
// back here again.
1648-
// Since we're restarting, remove anything that is not a host effect
1649-
// from the effect tag.
1650-
next.effectTag &= HostEffectMask;
1651-
workInProgress = next;
1652-
return;
1653-
}
1654-
16551656
if (returnFiber !== null) {
16561657
// Mark the parent fiber as incomplete and clear its effect list.
16571658
returnFiber.firstEffect = returnFiber.lastEffect = null;

packages/react-reconciler/src/ReactFiberWorkLoop.old.js

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1643,14 +1643,15 @@ function completeUnitOfWork(unitOfWork: Fiber): void {
16431643
stopProfilerTimerIfRunningAndRecordDelta(completedWork, false);
16441644
}
16451645
resetCurrentDebugFiberInDEV();
1646-
resetChildExpirationTime(completedWork);
16471646

16481647
if (next !== null) {
16491648
// Completing this fiber spawned new work. Work on that next.
16501649
workInProgress = next;
16511650
return;
16521651
}
16531652

1653+
resetChildExpirationTime(completedWork);
1654+
16541655
if (
16551656
returnFiber !== null &&
16561657
// Do not append effects to parents if a sibling failed to complete
@@ -1697,6 +1698,16 @@ function completeUnitOfWork(unitOfWork: Fiber): void {
16971698

16981699
// Because this fiber did not complete, don't reset its expiration time.
16991700

1701+
if (next !== null) {
1702+
// If completing this work spawned new work, do that next. We'll come
1703+
// back here again.
1704+
// Since we're restarting, remove anything that is not a host effect
1705+
// from the effect tag.
1706+
next.effectTag &= HostEffectMask;
1707+
workInProgress = next;
1708+
return;
1709+
}
1710+
17001711
if (
17011712
enableProfilerTimer &&
17021713
(completedWork.mode & ProfileMode) !== NoMode
@@ -1714,16 +1725,6 @@ function completeUnitOfWork(unitOfWork: Fiber): void {
17141725
completedWork.actualDuration = actualDuration;
17151726
}
17161727

1717-
if (next !== null) {
1718-
// If completing this work spawned new work, do that next. We'll come
1719-
// back here again.
1720-
// Since we're restarting, remove anything that is not a host effect
1721-
// from the effect tag.
1722-
next.effectTag &= HostEffectMask;
1723-
workInProgress = next;
1724-
return;
1725-
}
1726-
17271728
if (returnFiber !== null) {
17281729
// Mark the parent fiber as incomplete and clear its effect list.
17291730
returnFiber.firstEffect = returnFiber.lastEffect = null;

packages/react-reconciler/src/ReactProfilerTimer.new.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,17 @@ function startPassiveEffectTimer(): void {
148148
passiveEffectStartTime = now();
149149
}
150150

151+
function transferActualDuration(fiber: Fiber): void {
152+
// Transfer time spent rendering these children so we don't lose it
153+
// after we rerender. This is used as a helper in special cases
154+
// where we should count the work of multiple passes.
155+
let child = fiber.child;
156+
while (child) {
157+
fiber.actualDuration += child.actualDuration;
158+
child = child.sibling;
159+
}
160+
}
161+
151162
export {
152163
getCommitTime,
153164
recordCommitTime,
@@ -158,4 +169,5 @@ export {
158169
startProfilerTimer,
159170
stopProfilerTimerIfRunning,
160171
stopProfilerTimerIfRunningAndRecordDelta,
172+
transferActualDuration,
161173
};

packages/react-reconciler/src/ReactProfilerTimer.old.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,17 @@ function startPassiveEffectTimer(): void {
148148
passiveEffectStartTime = now();
149149
}
150150

151+
function transferActualDuration(fiber: Fiber): void {
152+
// Transfer time spent rendering these children so we don't lose it
153+
// after we rerender. This is used as a helper in special cases
154+
// where we should count the work of multiple passes.
155+
let child = fiber.child;
156+
while (child) {
157+
fiber.actualDuration += child.actualDuration;
158+
child = child.sibling;
159+
}
160+
}
161+
151162
export {
152163
getCommitTime,
153164
recordCommitTime,
@@ -158,4 +169,5 @@ export {
158169
startProfilerTimer,
159170
stopProfilerTimerIfRunning,
160171
stopProfilerTimerIfRunningAndRecordDelta,
172+
transferActualDuration,
161173
};

0 commit comments

Comments
 (0)