Skip to content

Commit

Permalink
[Fiber] Yield every other frame for Transition/Retry work (#31828)
Browse files Browse the repository at this point in the history
This flag first moves the `shouldYield()` logic into React itself. We
need this for `postTask` compatibility anyway since this logic is no
longer a concern of the scheduler. This means that there can also be no
global `requestPaint()` that asks for painting earlier. So this is best
rolled out with `enableAlwaysYieldScheduler` (and ideally
`enableYieldingBeforePassive`) instead of `enableRequestPaint`.

Once in React we can change the yield timing heuristics. This uses the
previous 5ms for Idle work to keep everything responsive while doing
background work. However, for Transitions and Retries we have seen that
same thread animations (like loading states animating, or constant
animations like cool Three.js stuff) can take CPU time away from the
Transition that causes moving into new content to slow down. Therefore
we only yield every 25ms.

The purpose of this yield is not to avoid the overhead of yielding,
which is very low, but rather to intentionally block any frequently
occurring other main thread work like animations from starving our work.
If we could we could just tell everyone else to throttle their stuff for
ideal scheduling but that's not quite realistic. In other words, the
purpose of this is to reduce the frame rate of animations to 30 fps and
we achieve this by not yielding. We still do yield to allow the
animations to not just stall. This seems like a good balance.

The 5ms of Idle is because we don't really need to yield less often
since the overhead is low. We keep it low to allow 120 fps animations to
run if necessary and our work may not be the only work within a frame so
we need to yield early enough to leave enough time left.

Similarly we choose 25ms rather than say 35ms to ensure that we push
long enough to guarantee to half the frame rate but low enough that
there's plenty of time left for a rAF to power each animation every
other frame. It's also low enough that if something else interrupts the
work like a new interaction, we can still be responsive to that within
50ms or so. We also need to yield in case there's I/O work that needs to
get bounced through the main thread.

This flag is currently off everywhere since we have so many other
scheduling flags but that means there's some urgency to roll those out
fully so we can test this one. There's also some tests to update since
this doesn't go through the Mock scheduler anymore for yields.

DiffTrain build for [fe21c94](fe21c94)
  • Loading branch information
sebmarkbage committed Jan 2, 2025
1 parent ee64237 commit e34e27e
Show file tree
Hide file tree
Showing 34 changed files with 126 additions and 126 deletions.
2 changes: 1 addition & 1 deletion compiled/facebook-www/REVISION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
de82912e620518d501680bbd93fbb5cc8d134223
1e9eb95db5b3a2064ecc26915a4e640b3a9bdaf5
2 changes: 1 addition & 1 deletion compiled/facebook-www/REVISION_TRANSFORMS
Original file line number Diff line number Diff line change
@@ -1 +1 @@
de82912e620518d501680bbd93fbb5cc8d134223
1e9eb95db5b3a2064ecc26915a4e640b3a9bdaf5
2 changes: 1 addition & 1 deletion compiled/facebook-www/React-dev.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -1942,7 +1942,7 @@ __DEV__ &&
exports.useTransition = function () {
return resolveDispatcher().useTransition();
};
exports.version = "19.1.0-www-classic-de82912e-20241220";
exports.version = "19.1.0-www-classic-fe21c947-20250102";
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
"function" ===
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&
Expand Down
2 changes: 1 addition & 1 deletion compiled/facebook-www/React-dev.modern.js
Original file line number Diff line number Diff line change
Expand Up @@ -1942,7 +1942,7 @@ __DEV__ &&
exports.useTransition = function () {
return resolveDispatcher().useTransition();
};
exports.version = "19.1.0-www-modern-de82912e-20241220";
exports.version = "19.1.0-www-modern-fe21c947-20250102";
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
"function" ===
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&
Expand Down
2 changes: 1 addition & 1 deletion compiled/facebook-www/React-prod.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -630,4 +630,4 @@ exports.useSyncExternalStore = function (
exports.useTransition = function () {
return ReactSharedInternals.H.useTransition();
};
exports.version = "19.1.0-www-classic-de82912e-20241220";
exports.version = "19.1.0-www-classic-fe21c947-20250102";
2 changes: 1 addition & 1 deletion compiled/facebook-www/React-prod.modern.js
Original file line number Diff line number Diff line change
Expand Up @@ -630,4 +630,4 @@ exports.useSyncExternalStore = function (
exports.useTransition = function () {
return ReactSharedInternals.H.useTransition();
};
exports.version = "19.1.0-www-modern-de82912e-20241220";
exports.version = "19.1.0-www-modern-fe21c947-20250102";
2 changes: 1 addition & 1 deletion compiled/facebook-www/React-profiling.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -634,7 +634,7 @@ exports.useSyncExternalStore = function (
exports.useTransition = function () {
return ReactSharedInternals.H.useTransition();
};
exports.version = "19.1.0-www-classic-de82912e-20241220";
exports.version = "19.1.0-www-classic-fe21c947-20250102";
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
"function" ===
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&
Expand Down
2 changes: 1 addition & 1 deletion compiled/facebook-www/React-profiling.modern.js
Original file line number Diff line number Diff line change
Expand Up @@ -634,7 +634,7 @@ exports.useSyncExternalStore = function (
exports.useTransition = function () {
return ReactSharedInternals.H.useTransition();
};
exports.version = "19.1.0-www-modern-de82912e-20241220";
exports.version = "19.1.0-www-modern-fe21c947-20250102";
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
"function" ===
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&
Expand Down
10 changes: 5 additions & 5 deletions compiled/facebook-www/ReactART-dev.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -13119,7 +13119,7 @@ __DEV__ &&
}
null !== ReactSharedInternals.actQueue
? workLoopSync()
: workLoopConcurrent();
: workLoopConcurrentByScheduler();
break;
} catch (thrownValue$35) {
handleThrow(root, thrownValue$35);
Expand All @@ -13144,7 +13144,7 @@ __DEV__ &&
finishQueueingConcurrentUpdates();
return workInProgressRootExitStatus;
}
function workLoopConcurrent() {
function workLoopConcurrentByScheduler() {
for (; null !== workInProgress && !shouldYield(); )
performUnitOfWork(workInProgress);
}
Expand Down Expand Up @@ -16894,10 +16894,10 @@ __DEV__ &&
(function () {
var internals = {
bundleType: 1,
version: "19.1.0-www-classic-de82912e-20241220",
version: "19.1.0-www-classic-fe21c947-20250102",
rendererPackageName: "react-art",
currentDispatcherRef: ReactSharedInternals,
reconcilerVersion: "19.1.0-www-classic-de82912e-20241220"
reconcilerVersion: "19.1.0-www-classic-fe21c947-20250102"
};
internals.overrideHookState = overrideHookState;
internals.overrideHookStateDeletePath = overrideHookStateDeletePath;
Expand Down Expand Up @@ -16931,7 +16931,7 @@ __DEV__ &&
exports.Shape = Shape;
exports.Surface = Surface;
exports.Text = Text;
exports.version = "19.1.0-www-classic-de82912e-20241220";
exports.version = "19.1.0-www-classic-fe21c947-20250102";
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
"function" ===
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&
Expand Down
10 changes: 5 additions & 5 deletions compiled/facebook-www/ReactART-dev.modern.js
Original file line number Diff line number Diff line change
Expand Up @@ -12923,7 +12923,7 @@ __DEV__ &&
}
null !== ReactSharedInternals.actQueue
? workLoopSync()
: workLoopConcurrent();
: workLoopConcurrentByScheduler();
break;
} catch (thrownValue$35) {
handleThrow(root, thrownValue$35);
Expand All @@ -12948,7 +12948,7 @@ __DEV__ &&
finishQueueingConcurrentUpdates();
return workInProgressRootExitStatus;
}
function workLoopConcurrent() {
function workLoopConcurrentByScheduler() {
for (; null !== workInProgress && !shouldYield(); )
performUnitOfWork(workInProgress);
}
Expand Down Expand Up @@ -16657,10 +16657,10 @@ __DEV__ &&
(function () {
var internals = {
bundleType: 1,
version: "19.1.0-www-modern-de82912e-20241220",
version: "19.1.0-www-modern-fe21c947-20250102",
rendererPackageName: "react-art",
currentDispatcherRef: ReactSharedInternals,
reconcilerVersion: "19.1.0-www-modern-de82912e-20241220"
reconcilerVersion: "19.1.0-www-modern-fe21c947-20250102"
};
internals.overrideHookState = overrideHookState;
internals.overrideHookStateDeletePath = overrideHookStateDeletePath;
Expand Down Expand Up @@ -16694,7 +16694,7 @@ __DEV__ &&
exports.Shape = Shape;
exports.Surface = Surface;
exports.Text = Text;
exports.version = "19.1.0-www-modern-de82912e-20241220";
exports.version = "19.1.0-www-modern-fe21c947-20250102";
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
"function" ===
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&
Expand Down
10 changes: 5 additions & 5 deletions compiled/facebook-www/ReactART-prod.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -9739,7 +9739,7 @@ function renderRootConcurrent(root, lanes) {
throw Error(formatProdErrorMessage(462));
}
}
workLoopConcurrent();
workLoopConcurrentByScheduler();
break;
} catch (thrownValue$139) {
handleThrow(root, thrownValue$139);
Expand All @@ -9755,7 +9755,7 @@ function renderRootConcurrent(root, lanes) {
finishQueueingConcurrentUpdates();
return workInProgressRootExitStatus;
}
function workLoopConcurrent() {
function workLoopConcurrentByScheduler() {
for (; null !== workInProgress && !shouldYield(); )
performUnitOfWork(workInProgress);
}
Expand Down Expand Up @@ -10779,10 +10779,10 @@ var slice = Array.prototype.slice,
})(React.Component);
var internals$jscomp$inline_1501 = {
bundleType: 0,
version: "19.1.0-www-classic-de82912e-20241220",
version: "19.1.0-www-classic-fe21c947-20250102",
rendererPackageName: "react-art",
currentDispatcherRef: ReactSharedInternals,
reconcilerVersion: "19.1.0-www-classic-de82912e-20241220"
reconcilerVersion: "19.1.0-www-classic-fe21c947-20250102"
};
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
var hook$jscomp$inline_1502 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
Expand All @@ -10808,4 +10808,4 @@ exports.RadialGradient = RadialGradient;
exports.Shape = TYPES.SHAPE;
exports.Surface = Surface;
exports.Text = Text;
exports.version = "19.1.0-www-classic-de82912e-20241220";
exports.version = "19.1.0-www-classic-fe21c947-20250102";
10 changes: 5 additions & 5 deletions compiled/facebook-www/ReactART-prod.modern.js
Original file line number Diff line number Diff line change
Expand Up @@ -9499,7 +9499,7 @@ function renderRootConcurrent(root, lanes) {
throw Error(formatProdErrorMessage(462));
}
}
workLoopConcurrent();
workLoopConcurrentByScheduler();
break;
} catch (thrownValue$139) {
handleThrow(root, thrownValue$139);
Expand All @@ -9515,7 +9515,7 @@ function renderRootConcurrent(root, lanes) {
finishQueueingConcurrentUpdates();
return workInProgressRootExitStatus;
}
function workLoopConcurrent() {
function workLoopConcurrentByScheduler() {
for (; null !== workInProgress && !shouldYield(); )
performUnitOfWork(workInProgress);
}
Expand Down Expand Up @@ -10495,10 +10495,10 @@ var slice = Array.prototype.slice,
})(React.Component);
var internals$jscomp$inline_1480 = {
bundleType: 0,
version: "19.1.0-www-modern-de82912e-20241220",
version: "19.1.0-www-modern-fe21c947-20250102",
rendererPackageName: "react-art",
currentDispatcherRef: ReactSharedInternals,
reconcilerVersion: "19.1.0-www-modern-de82912e-20241220"
reconcilerVersion: "19.1.0-www-modern-fe21c947-20250102"
};
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
var hook$jscomp$inline_1481 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
Expand All @@ -10524,4 +10524,4 @@ exports.RadialGradient = RadialGradient;
exports.Shape = TYPES.SHAPE;
exports.Surface = Surface;
exports.Text = Text;
exports.version = "19.1.0-www-modern-de82912e-20241220";
exports.version = "19.1.0-www-modern-fe21c947-20250102";
14 changes: 7 additions & 7 deletions compiled/facebook-www/ReactDOM-dev.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -16251,7 +16251,7 @@ __DEV__ &&
}
null !== ReactSharedInternals.actQueue
? workLoopSync()
: workLoopConcurrent();
: workLoopConcurrentByScheduler();
break;
} catch (thrownValue$39) {
handleThrow(root, thrownValue$39);
Expand All @@ -16276,7 +16276,7 @@ __DEV__ &&
finishQueueingConcurrentUpdates();
return workInProgressRootExitStatus;
}
function workLoopConcurrent() {
function workLoopConcurrentByScheduler() {
for (; null !== workInProgress && !shouldYield(); )
performUnitOfWork(workInProgress);
}
Expand Down Expand Up @@ -27374,11 +27374,11 @@ __DEV__ &&
return_targetInst = null;
(function () {
var isomorphicReactPackageVersion = React.version;
if ("19.1.0-www-classic-de82912e-20241220" !== isomorphicReactPackageVersion)
if ("19.1.0-www-classic-fe21c947-20250102" !== isomorphicReactPackageVersion)
throw Error(
'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' +
(isomorphicReactPackageVersion +
"\n - react-dom: 19.1.0-www-classic-de82912e-20241220\nLearn more: https://react.dev/warnings/version-mismatch")
"\n - react-dom: 19.1.0-www-classic-fe21c947-20250102\nLearn more: https://react.dev/warnings/version-mismatch")
);
})();
("function" === typeof Map &&
Expand Down Expand Up @@ -27421,10 +27421,10 @@ __DEV__ &&
!(function () {
var internals = {
bundleType: 1,
version: "19.1.0-www-classic-de82912e-20241220",
version: "19.1.0-www-classic-fe21c947-20250102",
rendererPackageName: "react-dom",
currentDispatcherRef: ReactSharedInternals,
reconcilerVersion: "19.1.0-www-classic-de82912e-20241220"
reconcilerVersion: "19.1.0-www-classic-fe21c947-20250102"
};
internals.overrideHookState = overrideHookState;
internals.overrideHookStateDeletePath = overrideHookStateDeletePath;
Expand Down Expand Up @@ -28022,7 +28022,7 @@ __DEV__ &&
exports.useFormStatus = function () {
return resolveDispatcher().useHostTransitionStatus();
};
exports.version = "19.1.0-www-classic-de82912e-20241220";
exports.version = "19.1.0-www-classic-fe21c947-20250102";
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
"function" ===
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&
Expand Down
14 changes: 7 additions & 7 deletions compiled/facebook-www/ReactDOM-dev.modern.js
Original file line number Diff line number Diff line change
Expand Up @@ -16050,7 +16050,7 @@ __DEV__ &&
}
null !== ReactSharedInternals.actQueue
? workLoopSync()
: workLoopConcurrent();
: workLoopConcurrentByScheduler();
break;
} catch (thrownValue$39) {
handleThrow(root, thrownValue$39);
Expand All @@ -16075,7 +16075,7 @@ __DEV__ &&
finishQueueingConcurrentUpdates();
return workInProgressRootExitStatus;
}
function workLoopConcurrent() {
function workLoopConcurrentByScheduler() {
for (; null !== workInProgress && !shouldYield(); )
performUnitOfWork(workInProgress);
}
Expand Down Expand Up @@ -27153,11 +27153,11 @@ __DEV__ &&
return_targetInst = null;
(function () {
var isomorphicReactPackageVersion = React.version;
if ("19.1.0-www-modern-de82912e-20241220" !== isomorphicReactPackageVersion)
if ("19.1.0-www-modern-fe21c947-20250102" !== isomorphicReactPackageVersion)
throw Error(
'Incompatible React versions: The "react" and "react-dom" packages must have the exact same version. Instead got:\n - react: ' +
(isomorphicReactPackageVersion +
"\n - react-dom: 19.1.0-www-modern-de82912e-20241220\nLearn more: https://react.dev/warnings/version-mismatch")
"\n - react-dom: 19.1.0-www-modern-fe21c947-20250102\nLearn more: https://react.dev/warnings/version-mismatch")
);
})();
("function" === typeof Map &&
Expand Down Expand Up @@ -27200,10 +27200,10 @@ __DEV__ &&
!(function () {
var internals = {
bundleType: 1,
version: "19.1.0-www-modern-de82912e-20241220",
version: "19.1.0-www-modern-fe21c947-20250102",
rendererPackageName: "react-dom",
currentDispatcherRef: ReactSharedInternals,
reconcilerVersion: "19.1.0-www-modern-de82912e-20241220"
reconcilerVersion: "19.1.0-www-modern-fe21c947-20250102"
};
internals.overrideHookState = overrideHookState;
internals.overrideHookStateDeletePath = overrideHookStateDeletePath;
Expand Down Expand Up @@ -27801,7 +27801,7 @@ __DEV__ &&
exports.useFormStatus = function () {
return resolveDispatcher().useHostTransitionStatus();
};
exports.version = "19.1.0-www-modern-de82912e-20241220";
exports.version = "19.1.0-www-modern-fe21c947-20250102";
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
"function" ===
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&
Expand Down
14 changes: 7 additions & 7 deletions compiled/facebook-www/ReactDOM-prod.classic.js
Original file line number Diff line number Diff line change
Expand Up @@ -11611,7 +11611,7 @@ function renderRootConcurrent(root, lanes) {
throw Error(formatProdErrorMessage(462));
}
}
workLoopConcurrent();
workLoopConcurrentByScheduler();
break;
} catch (thrownValue$192) {
handleThrow(root, thrownValue$192);
Expand All @@ -11627,7 +11627,7 @@ function renderRootConcurrent(root, lanes) {
finishQueueingConcurrentUpdates();
return workInProgressRootExitStatus;
}
function workLoopConcurrent() {
function workLoopConcurrentByScheduler() {
for (; null !== workInProgress && !shouldYield(); )
performUnitOfWork(workInProgress);
}
Expand Down Expand Up @@ -17244,14 +17244,14 @@ function getCrossOriginStringAs(as, input) {
}
var isomorphicReactPackageVersion$jscomp$inline_1770 = React.version;
if (
"19.1.0-www-classic-de82912e-20241220" !==
"19.1.0-www-classic-fe21c947-20250102" !==
isomorphicReactPackageVersion$jscomp$inline_1770
)
throw Error(
formatProdErrorMessage(
527,
isomorphicReactPackageVersion$jscomp$inline_1770,
"19.1.0-www-classic-de82912e-20241220"
"19.1.0-www-classic-fe21c947-20250102"
)
);
Internals.findDOMNode = function (componentOrElement) {
Expand All @@ -17269,10 +17269,10 @@ Internals.Events = [
];
var internals$jscomp$inline_2307 = {
bundleType: 0,
version: "19.1.0-www-classic-de82912e-20241220",
version: "19.1.0-www-classic-fe21c947-20250102",
rendererPackageName: "react-dom",
currentDispatcherRef: ReactSharedInternals,
reconcilerVersion: "19.1.0-www-classic-de82912e-20241220"
reconcilerVersion: "19.1.0-www-classic-fe21c947-20250102"
};
if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {
var hook$jscomp$inline_2308 = __REACT_DEVTOOLS_GLOBAL_HOOK__;
Expand Down Expand Up @@ -17637,4 +17637,4 @@ exports.useFormState = function (action, initialState, permalink) {
exports.useFormStatus = function () {
return ReactSharedInternals.H.useHostTransitionStatus();
};
exports.version = "19.1.0-www-classic-de82912e-20241220";
exports.version = "19.1.0-www-classic-fe21c947-20250102";
Loading

0 comments on commit e34e27e

Please sign in to comment.