Skip to content

Commit 979b115

Browse files
authored
Revert "Use Global Render Timeout for CPU Suspense (#19643)"
This reverts commit d6e4338.
1 parent 1f38dcf commit 979b115

11 files changed

+50
-265
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2628,6 +2628,7 @@ function initSuspenseListRenderState(
26282628
renderingStartTime: 0,
26292629
last: lastContentRow,
26302630
tail: tail,
2631+
tailExpiration: 0,
26312632
tailMode: tailMode,
26322633
}: SuspenseListRenderState);
26332634
} else {
@@ -2637,6 +2638,7 @@ function initSuspenseListRenderState(
26372638
renderState.renderingStartTime = 0;
26382639
renderState.last = lastContentRow;
26392640
renderState.tail = tail;
2641+
renderState.tailExpiration = 0;
26402642
renderState.tailMode = tailMode;
26412643
}
26422644
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2635,6 +2635,7 @@ function initSuspenseListRenderState(
26352635
renderingStartTime: 0,
26362636
last: lastContentRow,
26372637
tail: tail,
2638+
tailExpiration: 0,
26382639
tailMode: tailMode,
26392640
lastEffect: lastEffectBeforeRendering,
26402641
}: SuspenseListRenderState);
@@ -2645,6 +2646,7 @@ function initSuspenseListRenderState(
26452646
renderState.renderingStartTime = 0;
26462647
renderState.last = lastContentRow;
26472648
renderState.tail = tail;
2649+
renderState.tailExpiration = 0;
26482650
renderState.tailMode = tailMode;
26492651
renderState.lastEffect = lastEffectBeforeRendering;
26502652
}

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

Lines changed: 18 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,9 @@ import {
137137
renderDidSuspendDelayIfPossible,
138138
renderHasNotSuspendedYet,
139139
popRenderLanes,
140-
getRenderTargetTime,
141140
} from './ReactFiberWorkLoop.new';
142141
import {createFundamentalStateInstance} from './ReactFiberFundamental.new';
143-
import {OffscreenLane, SomeRetryLane} from './ReactFiberLane';
142+
import {OffscreenLane} from './ReactFiberLane';
144143
import {resetChildFibers} from './ReactChildFiber.new';
145144
import {createScopeInstance} from './ReactFiberScope.new';
146145
import {transferActualDuration} from './ReactProfilerTimer.new';
@@ -1067,29 +1066,6 @@ function completeWork(
10671066
row = row.sibling;
10681067
}
10691068
}
1070-
1071-
if (renderState.tail !== null && now() > getRenderTargetTime()) {
1072-
// We have already passed our CPU deadline but we still have rows
1073-
// left in the tail. We'll just give up further attempts to render
1074-
// the main content and only render fallbacks.
1075-
workInProgress.effectTag |= DidCapture;
1076-
didSuspendAlready = true;
1077-
1078-
cutOffTailIfNeeded(renderState, false);
1079-
1080-
// Since nothing actually suspended, there will nothing to ping this
1081-
// to get it started back up to attempt the next item. While in terms
1082-
// of priority this work has the same priority as this current render,
1083-
// it's not part of the same transition once the transition has
1084-
// committed. If it's sync, we still want to yield so that it can be
1085-
// painted. Conceptually, this is really the same as pinging.
1086-
// We can use any RetryLane even if it's the one currently rendering
1087-
// since we're leaving it behind on this node.
1088-
workInProgress.lanes = SomeRetryLane;
1089-
if (enableSchedulerTracing) {
1090-
markSpawnedWork(SomeRetryLane);
1091-
}
1092-
}
10931069
} else {
10941070
cutOffTailIfNeeded(renderState, false);
10951071
}
@@ -1122,11 +1098,10 @@ function completeWork(
11221098
return null;
11231099
}
11241100
} else if (
1125-
// The time it took to render last row is greater than the remaining
1126-
// time we have to render. So rendering one more row would likely
1127-
// exceed it.
1101+
// The time it took to render last row is greater than time until
1102+
// the expiration.
11281103
now() * 2 - renderState.renderingStartTime >
1129-
getRenderTargetTime() &&
1104+
renderState.tailExpiration &&
11301105
renderLanes !== OffscreenLane
11311106
) {
11321107
// We have now passed our CPU deadline and we'll just give up further
@@ -1142,9 +1117,9 @@ function completeWork(
11421117
// them, then they really have the same priority as this render.
11431118
// So we'll pick it back up the very next render pass once we've had
11441119
// an opportunity to yield for paint.
1145-
workInProgress.lanes = SomeRetryLane;
1120+
workInProgress.lanes = renderLanes;
11461121
if (enableSchedulerTracing) {
1147-
markSpawnedWork(SomeRetryLane);
1122+
markSpawnedWork(renderLanes);
11481123
}
11491124
}
11501125
}
@@ -1169,6 +1144,18 @@ function completeWork(
11691144

11701145
if (renderState.tail !== null) {
11711146
// We still have tail rows to render.
1147+
if (renderState.tailExpiration === 0) {
1148+
// Heuristic for how long we're willing to spend rendering rows
1149+
// until we just give up and show what we have so far.
1150+
const TAIL_EXPIRATION_TIMEOUT_MS = 500;
1151+
renderState.tailExpiration = now() + TAIL_EXPIRATION_TIMEOUT_MS;
1152+
// TODO: This is meant to mimic the train model or JND but this
1153+
// is a per component value. It should really be since the start
1154+
// of the total render or last commit. Consider using something like
1155+
// globalMostRecentFallbackTime. That doesn't account for being
1156+
// suspended for part of the time or when it's a new render.
1157+
// It should probably use a global start time value instead.
1158+
}
11721159
// Pop a row.
11731160
const next = renderState.tail;
11741161
renderState.rendering = next;

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

Lines changed: 22 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -135,10 +135,9 @@ import {
135135
renderDidSuspendDelayIfPossible,
136136
renderHasNotSuspendedYet,
137137
popRenderLanes,
138-
getRenderTargetTime,
139138
} from './ReactFiberWorkLoop.old';
140139
import {createFundamentalStateInstance} from './ReactFiberFundamental.old';
141-
import {OffscreenLane, SomeRetryLane} from './ReactFiberLane';
140+
import {OffscreenLane} from './ReactFiberLane';
142141
import {resetChildFibers} from './ReactChildFiber.old';
143142
import {createScopeInstance} from './ReactFiberScope.old';
144143
import {transferActualDuration} from './ReactProfilerTimer.old';
@@ -1050,29 +1049,6 @@ function completeWork(
10501049
row = row.sibling;
10511050
}
10521051
}
1053-
1054-
if (renderState.tail !== null && now() > getRenderTargetTime()) {
1055-
// We have already passed our CPU deadline but we still have rows
1056-
// left in the tail. We'll just give up further attempts to render
1057-
// the main content and only render fallbacks.
1058-
workInProgress.effectTag |= DidCapture;
1059-
didSuspendAlready = true;
1060-
1061-
cutOffTailIfNeeded(renderState, false);
1062-
1063-
// Since nothing actually suspended, there will nothing to ping this
1064-
// to get it started back up to attempt the next item. While in terms
1065-
// of priority this work has the same priority as this current render,
1066-
// it's not part of the same transition once the transition has
1067-
// committed. If it's sync, we still want to yield so that it can be
1068-
// painted. Conceptually, this is really the same as pinging.
1069-
// We can use any RetryLane even if it's the one currently rendering
1070-
// since we're leaving it behind on this node.
1071-
workInProgress.lanes = SomeRetryLane;
1072-
if (enableSchedulerTracing) {
1073-
markSpawnedWork(SomeRetryLane);
1074-
}
1075-
}
10761052
} else {
10771053
cutOffTailIfNeeded(renderState, false);
10781054
}
@@ -1114,11 +1090,10 @@ function completeWork(
11141090
return null;
11151091
}
11161092
} else if (
1117-
// The time it took to render last row is greater than the remaining
1118-
// time we have to render. So rendering one more row would likely
1119-
// exceed it.
1093+
// The time it took to render last row is greater than time until
1094+
// the expiration.
11201095
now() * 2 - renderState.renderingStartTime >
1121-
getRenderTargetTime() &&
1096+
renderState.tailExpiration &&
11221097
renderLanes !== OffscreenLane
11231098
) {
11241099
// We have now passed our CPU deadline and we'll just give up further
@@ -1130,16 +1105,13 @@ function completeWork(
11301105
cutOffTailIfNeeded(renderState, false);
11311106

11321107
// Since nothing actually suspended, there will nothing to ping this
1133-
// to get it started back up to attempt the next item. While in terms
1134-
// of priority this work has the same priority as this current render,
1135-
// it's not part of the same transition once the transition has
1136-
// committed. If it's sync, we still want to yield so that it can be
1137-
// painted. Conceptually, this is really the same as pinging.
1138-
// We can use any RetryLane even if it's the one currently rendering
1139-
// since we're leaving it behind on this node.
1140-
workInProgress.lanes = SomeRetryLane;
1108+
// to get it started back up to attempt the next item. If we can show
1109+
// them, then they really have the same priority as this render.
1110+
// So we'll pick it back up the very next render pass once we've had
1111+
// an opportunity to yield for paint.
1112+
workInProgress.lanes = renderLanes;
11411113
if (enableSchedulerTracing) {
1142-
markSpawnedWork(SomeRetryLane);
1114+
markSpawnedWork(renderLanes);
11431115
}
11441116
}
11451117
}
@@ -1164,6 +1136,18 @@ function completeWork(
11641136

11651137
if (renderState.tail !== null) {
11661138
// We still have tail rows to render.
1139+
if (renderState.tailExpiration === 0) {
1140+
// Heuristic for how long we're willing to spend rendering rows
1141+
// until we just give up and show what we have so far.
1142+
const TAIL_EXPIRATION_TIMEOUT_MS = 500;
1143+
renderState.tailExpiration = now() + TAIL_EXPIRATION_TIMEOUT_MS;
1144+
// TODO: This is meant to mimic the train model or JND but this
1145+
// is a per component value. It should really be since the start
1146+
// of the total render or last commit. Consider using something like
1147+
// globalMostRecentFallbackTime. That doesn't account for being
1148+
// suspended for part of the time or when it's a new render.
1149+
// It should probably use a global start time value instead.
1150+
}
11671151
// Pop a row.
11681152
const next = renderState.tail;
11691153
renderState.rendering = next;

packages/react-reconciler/src/ReactFiberLane.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,6 @@ const TransitionLanes: Lanes = /* */ 0b0000000001111111110
9191

9292
const RetryLanes: Lanes = /* */ 0b0000011110000000000000000000000;
9393

94-
export const SomeRetryLane: Lanes = /* */ 0b0000010000000000000000000000000;
95-
9694
export const SelectiveHydrationLane: Lane = /* */ 0b0000100000000000000000000000000;
9795

9896
const NonIdleLanes = /* */ 0b0000111111111111111111111111111;

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,14 @@ export type SuspenseListRenderState = {|
4141
isBackwards: boolean,
4242
// The currently rendering tail row.
4343
rendering: null | Fiber,
44-
// The absolute time when we started rendering the most recent tail row.
44+
// The absolute time when we started rendering the tail row.
4545
renderingStartTime: number,
4646
// The last of the already rendered children.
4747
last: null | Fiber,
4848
// Remaining rows on the tail of the list.
4949
tail: null | Fiber,
50+
// The absolute time in ms that we'll expire the tail rendering.
51+
tailExpiration: number,
5052
// Tail insertions setting.
5153
tailMode: SuspenseListTailMode,
5254
|};

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,14 @@ export type SuspenseListRenderState = {|
4141
isBackwards: boolean,
4242
// The currently rendering tail row.
4343
rendering: null | Fiber,
44-
// The absolute time when we started rendering the most recent tail row.
44+
// The absolute time when we started rendering the tail row.
4545
renderingStartTime: number,
4646
// The last of the already rendered children.
4747
last: null | Fiber,
4848
// Remaining rows on the tail of the list.
4949
tail: null | Fiber,
50+
// The absolute time in ms that we'll expire the tail rendering.
51+
tailExpiration: number,
5052
// Tail insertions setting.
5153
tailMode: SuspenseListTailMode,
5254
// Last Effect before we rendered the "rendering" item.

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

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -323,21 +323,6 @@ let mostRecentlyUpdatedRoot: FiberRoot | null = null;
323323
let globalMostRecentFallbackTime: number = 0;
324324
const FALLBACK_THROTTLE_MS: number = 500;
325325

326-
// The absolute time for when we should start giving up on rendering
327-
// more and prefer CPU suspense heuristics instead.
328-
let workInProgressRootRenderTargetTime: number = Infinity;
329-
// How long a render is supposed to take before we start following CPU
330-
// suspense heuristics and opt out of rendering more content.
331-
const RENDER_TIMEOUT_MS = 500;
332-
333-
function resetRenderTimer() {
334-
workInProgressRootRenderTargetTime = now() + RENDER_TIMEOUT_MS;
335-
}
336-
337-
export function getRenderTargetTime(): number {
338-
return workInProgressRootRenderTargetTime;
339-
}
340-
341326
let hasUncaughtError = false;
342327
let firstUncaughtError = null;
343328
let legacyErrorBoundariesThatAlreadyFailed: Set<mixed> | null = null;
@@ -597,7 +582,6 @@ export function scheduleUpdateOnFiber(
597582
// scheduleCallbackForFiber to preserve the ability to schedule a callback
598583
// without immediately flushing it. We only do this for user-initiated
599584
// updates, to preserve historical behavior of legacy mode.
600-
resetRenderTimer();
601585
flushSyncCallbackQueue();
602586
}
603587
}
@@ -1061,7 +1045,6 @@ export function flushRoot(root: FiberRoot, lanes: Lanes) {
10611045
markRootExpired(root, lanes);
10621046
ensureRootIsScheduled(root, now());
10631047
if ((executionContext & (RenderContext | CommitContext)) === NoContext) {
1064-
resetRenderTimer();
10651048
flushSyncCallbackQueue();
10661049
}
10671050
}
@@ -1136,7 +1119,6 @@ export function batchedUpdates<A, R>(fn: A => R, a: A): R {
11361119
executionContext = prevExecutionContext;
11371120
if (executionContext === NoContext) {
11381121
// Flush the immediate callbacks that were scheduled during this batch
1139-
resetRenderTimer();
11401122
flushSyncCallbackQueue();
11411123
}
11421124
}
@@ -1151,7 +1133,6 @@ export function batchedEventUpdates<A, R>(fn: A => R, a: A): R {
11511133
executionContext = prevExecutionContext;
11521134
if (executionContext === NoContext) {
11531135
// Flush the immediate callbacks that were scheduled during this batch
1154-
resetRenderTimer();
11551136
flushSyncCallbackQueue();
11561137
}
11571138
}
@@ -1180,7 +1161,6 @@ export function discreteUpdates<A, B, C, D, R>(
11801161
executionContext = prevExecutionContext;
11811162
if (executionContext === NoContext) {
11821163
// Flush the immediate callbacks that were scheduled during this batch
1183-
resetRenderTimer();
11841164
flushSyncCallbackQueue();
11851165
}
11861166
}
@@ -1194,7 +1174,6 @@ export function discreteUpdates<A, B, C, D, R>(
11941174
executionContext = prevExecutionContext;
11951175
if (executionContext === NoContext) {
11961176
// Flush the immediate callbacks that were scheduled during this batch
1197-
resetRenderTimer();
11981177
flushSyncCallbackQueue();
11991178
}
12001179
}
@@ -1211,7 +1190,6 @@ export function unbatchedUpdates<A, R>(fn: (a: A) => R, a: A): R {
12111190
executionContext = prevExecutionContext;
12121191
if (executionContext === NoContext) {
12131192
// Flush the immediate callbacks that were scheduled during this batch
1214-
resetRenderTimer();
12151193
flushSyncCallbackQueue();
12161194
}
12171195
}
@@ -1279,7 +1257,6 @@ export function flushControlled(fn: () => mixed): void {
12791257
executionContext = prevExecutionContext;
12801258
if (executionContext === NoContext) {
12811259
// Flush the immediate callbacks that were scheduled during this batch
1282-
resetRenderTimer();
12831260
flushSyncCallbackQueue();
12841261
}
12851262
}
@@ -1290,7 +1267,6 @@ export function flushControlled(fn: () => mixed): void {
12901267
executionContext = prevExecutionContext;
12911268
if (executionContext === NoContext) {
12921269
// Flush the immediate callbacks that were scheduled during this batch
1293-
resetRenderTimer();
12941270
flushSyncCallbackQueue();
12951271
}
12961272
}
@@ -1583,7 +1559,6 @@ function renderRootConcurrent(root: FiberRoot, lanes: Lanes) {
15831559
// If the root or lanes have changed, throw out the existing stack
15841560
// and prepare a fresh one. Otherwise we'll continue where we left off.
15851561
if (workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes) {
1586-
resetRenderTimer();
15871562
prepareFreshStack(root, lanes);
15881563
startWorkOnPendingInteractions(root, lanes);
15891564
}

0 commit comments

Comments
 (0)