@samitouri / QOS-React-1 / commits / 0cdfef19b9

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.