Add feature flags for expiration times (#27821)
It seems worthwhile to me to run a test to experiment with different expiration times. This moves the expiration times for scheduler and reconciler into FeatureFlags for the facebook build. Non-facebook should not be affected by these changes.
Jan Kassens committed
Dec 11, 2023 at 09:58 UTC
0cdfef19b96cc6202d48e0812b5069c286d12b04
13 files changed
+68
-20
packages/react-reconciler/src/ReactFiberLane.js
+8
-3
@@ -25,6 +25,9 @@ import {
25
enableTransitionTracing,
26
enableUnifiedSyncLane,
27
enableUpdaterTracking,
28
+ syncLaneExpirationMs,
29
+ transitionLaneExpirationMs,
30
+ retryLaneExpirationMs,
31
} from 'shared/ReactFeatureFlags';
32
import {isDevToolsPresent} from './ReactFiberDevToolsHook';
33
import {ConcurrentUpdatesByDefaultMode, NoMode} from './ReactTypeOfMode';
@@ -355,7 +358,7 @@ function computeExpirationTime(lane: Lane, currentTime: number) {
358
// to fix the starvation. However, this scenario supports the idea that
359
// expiration times are an important safeguard when starvation
360
// does happen.
358
- return currentTime + 250;
361
+ return currentTime + syncLaneExpirationMs;
362
case DefaultHydrationLane:
363
case DefaultLane:
364
case TransitionHydrationLane:
@@ -374,7 +377,7 @@ function computeExpirationTime(lane: Lane, currentTime: number) {
377
case TransitionLane13:
378
case TransitionLane14:
379
case TransitionLane15:
377
- return currentTime + 5000;
380
+ return currentTime + transitionLaneExpirationMs;
381
case RetryLane1:
382
case RetryLane2:
383
case RetryLane3:
@@ -384,7 +387,9 @@ function computeExpirationTime(lane: Lane, currentTime: number) {
387
// crashes. There must be some other underlying bug; not super urgent but
388
// ideally should figure out why and fix it. Unfortunately we don't have
389
// a repro for the crashes, only detected via production metrics.
387
- return enableRetryLaneExpiration ? currentTime + 5000 : NoTimestamp;
390
+ return enableRetryLaneExpiration
391
+ ? currentTime + retryLaneExpirationMs
392
+ : NoTimestamp;
393
case SelectiveHydrationLane:
394
case IdleHydrationLane:
395
case IdleLane:
packages/scheduler/src/SchedulerFeatureFlags.js
+4
@@ -14,3 +14,7 @@ export const enableIsInputPendingContinuous = false;
14
export const frameYieldMs = 5;
15
export const continuousYieldMs = 50;
16
export const maxYieldMs = 300;
17
+
18
+export const userBlockingPriorityTimeout = 250;
19
+export const normalPriorityTimeout = 5000;
20
+export const lowPriorityTimeout = 10000;
packages/scheduler/src/forks/Scheduler.js
+13
-14
@@ -19,6 +19,9 @@ import {
19
frameYieldMs,
20
continuousYieldMs,
21
maxYieldMs,
22
+ userBlockingPriorityTimeout,
23
+ lowPriorityTimeout,
24
+ normalPriorityTimeout,
25
} from '../SchedulerFeatureFlags';
26
27
import {push, pop, peek} from '../SchedulerMinHeap';
@@ -75,15 +78,6 @@ if (hasPerformanceNow) {
78
// 0b111111111111111111111111111111
79
var maxSigned31BitInt = 1073741823;
80
78
-// Times out immediately
79
-var IMMEDIATE_PRIORITY_TIMEOUT = -1;
80
-// Eventually times out
81
-var USER_BLOCKING_PRIORITY_TIMEOUT = 250;
82
-var NORMAL_PRIORITY_TIMEOUT = 5000;
83
-var LOW_PRIORITY_TIMEOUT = 10000;
84
-// Never times out
85
-var IDLE_PRIORITY_TIMEOUT = maxSigned31BitInt;
86
-
81
// Tasks are stored on a min heap
82
var taskQueue: Array<Task> = [];
83
var timerQueue: Array<Task> = [];
@@ -362,20 +356,25 @@ function unstable_scheduleCallback(
356
var timeout;
357
switch (priorityLevel) {
358
case ImmediatePriority:
365
- timeout = IMMEDIATE_PRIORITY_TIMEOUT;
359
+ // Times out immediately
360
+ timeout = -1;
361
break;
362
case UserBlockingPriority:
368
- timeout = USER_BLOCKING_PRIORITY_TIMEOUT;
363
+ // Eventually times out
364
+ timeout = userBlockingPriorityTimeout;
365
break;
366
case IdlePriority:
371
- timeout = IDLE_PRIORITY_TIMEOUT;
367
+ // Never times out
368
+ timeout = maxSigned31BitInt;
369
break;
370
case LowPriority:
374
- timeout = LOW_PRIORITY_TIMEOUT;
371
+ // Eventually times out
372
+ timeout = lowPriorityTimeout;
373
break;
374
case NormalPriority:
375
default:
378
- timeout = NORMAL_PRIORITY_TIMEOUT;
376
+ // Eventually times out
377
+ timeout = normalPriorityTimeout;
378
break;
379
}
380
packages/scheduler/src/forks/SchedulerFeatureFlags.www-dynamic.js
+4
@@ -12,3 +12,7 @@
12
// with the __VARIANT__ set to `true`, and once set to `false`.
13
14
export const enableProfiling = __VARIANT__;
15
+
16
+export const userBlockingPriorityTimeout = 250;
17
+export const normalPriorityTimeout = 5000;
18
+export const lowPriorityTimeout = 10000;
packages/scheduler/src/forks/SchedulerFeatureFlags.www.js
+9
-3
@@ -7,10 +7,16 @@
7
* @flow
8
*/
9
10
-const {enableProfiling: enableProfilingFeatureFlag} =
11
- // $FlowFixMe[cannot-resolve-module]
12
- require('SchedulerFeatureFlags');
10
+// $FlowFixMe[cannot-resolve-module]
11
+const dynamicFeatureFlags = require('SchedulerFeatureFlags');
12
13
+const {enableProfiling: enableProfilingFeatureFlag} = dynamicFeatureFlags;
14
+
15
+export const {
16
+ userBlockingPriorityTimeout,
17
+ normalPriorityTimeout,
18
+ lowPriorityTimeout,
19
+} = dynamicFeatureFlags;
20
export const enableSchedulerDebugging = true;
21
export const enableProfiling: boolean =
22
__PROFILE__ && enableProfilingFeatureFlag;
packages/shared/ReactFeatureFlags.js
+3
@@ -130,6 +130,9 @@ export const enableUseDeferredValueInitialArg = __EXPERIMENTAL__;
130
* Enables an expiration time for retry lanes to avoid starvation.
131
*/
132
export const enableRetryLaneExpiration = false;
133
+export const retryLaneExpirationMs = 5000;
134
+export const syncLaneExpirationMs = 250;
135
+export const transitionLaneExpirationMs = 5000;
136
137
// -----------------------------------------------------------------------------
138
// Chopping Block
packages/shared/forks/ReactFeatureFlags.native-fb.js
+4
@@ -66,7 +66,11 @@ export const enableComponentStackLocations = false;
66
export const enableLegacyFBSupport = false;
67
export const enableFilterEmptyStringAttributesDOM = false;
68
export const enableGetInspectorDataForInstanceInProduction = true;
69
+
70
export const enableRetryLaneExpiration = false;
71
+export const retryLaneExpirationMs = 5000;
72
+export const syncLaneExpirationMs = 250;
73
+export const transitionLaneExpirationMs = 5000;
74
75
export const createRootStrictEffectsByDefault = false;
76
packages/shared/forks/ReactFeatureFlags.native-oss.js
+4
@@ -49,7 +49,11 @@ export const enableComponentStackLocations = false;
49
export const enableLegacyFBSupport = false;
50
export const enableFilterEmptyStringAttributesDOM = false;
51
export const enableGetInspectorDataForInstanceInProduction = false;
52
+
53
export const enableRetryLaneExpiration = false;
54
+export const retryLaneExpirationMs = 5000;
55
+export const syncLaneExpirationMs = 250;
56
+export const transitionLaneExpirationMs = 5000;
57
58
export const createRootStrictEffectsByDefault = false;
59
export const enableUseRefAccessWarning = false;
packages/shared/forks/ReactFeatureFlags.test-renderer.js
+4
@@ -49,7 +49,11 @@ export const enableComponentStackLocations = true;
49
export const enableLegacyFBSupport = false;
50
export const enableFilterEmptyStringAttributesDOM = false;
51
export const enableGetInspectorDataForInstanceInProduction = false;
52
+
53
export const enableRetryLaneExpiration = false;
54
+export const retryLaneExpirationMs = 5000;
55
+export const syncLaneExpirationMs = 250;
56
+export const transitionLaneExpirationMs = 5000;
57
58
export const createRootStrictEffectsByDefault = false;
59
export const enableUseRefAccessWarning = false;
packages/shared/forks/ReactFeatureFlags.test-renderer.native.js
+4
@@ -51,7 +51,11 @@ export const enableUseEffectEventHook = false;
51
export const enableClientRenderFallbackOnTextMismatch = true;
52
export const createRootStrictEffectsByDefault = false;
53
export const enableUseRefAccessWarning = false;
54
+
55
export const enableRetryLaneExpiration = false;
56
+export const retryLaneExpirationMs = 5000;
57
+export const syncLaneExpirationMs = 250;
58
+export const transitionLaneExpirationMs = 5000;
59
60
export const disableSchedulerTimeoutInWorkLoop = false;
61
export const enableLazyContextPropagation = false;
packages/shared/forks/ReactFeatureFlags.test-renderer.www.js
+4
@@ -49,7 +49,11 @@ export const enableComponentStackLocations = true;
49
export const enableLegacyFBSupport = false;
50
export const enableFilterEmptyStringAttributesDOM = true;
51
export const enableGetInspectorDataForInstanceInProduction = false;
52
+
53
export const enableRetryLaneExpiration = false;
54
+export const retryLaneExpirationMs = 5000;
55
+export const syncLaneExpirationMs = 250;
56
+export const transitionLaneExpirationMs = 5000;
57
58
export const createRootStrictEffectsByDefault = false;
59
export const enableUseRefAccessWarning = false;
packages/shared/forks/ReactFeatureFlags.www-dynamic.js
+4
@@ -29,7 +29,11 @@ export const enableAsyncActions = __VARIANT__;
29
export const alwaysThrottleRetries = __VARIANT__;
30
export const enableDO_NOT_USE_disableStrictPassiveEffect = __VARIANT__;
31
export const enableUseDeferredValueInitialArg = __VARIANT__;
32
+
33
export const enableRetryLaneExpiration = __VARIANT__;
34
+export const retryLaneExpirationMs = 5000;
35
+export const syncLaneExpirationMs = 250;
36
+export const transitionLaneExpirationMs = 5000;
37
38
// Enable this flag to help with concurrent mode debugging.
39
// It logs information to the console about React scheduling, rendering, and commit phases.
packages/shared/forks/ReactFeatureFlags.www.js
+3
@@ -33,6 +33,9 @@ export const {
33
enableDO_NOT_USE_disableStrictPassiveEffect,
34
disableSchedulerTimeoutInWorkLoop,
35
enableUseDeferredValueInitialArg,
36
+ retryLaneExpirationMs,
37
+ syncLaneExpirationMs,
38
+ transitionLaneExpirationMs,
39
} = dynamicFeatureFlags;
40
41
// On WWW, __EXPERIMENTAL__ is used for a new modern build.