Skip to content

Commit 40cddfe

Browse files
taneliangkartikchobvaughn
authored
Add user timing marks for scheduling profiler tool (#19223)
High level breakdown of this commit: * Add a enableSchedulingProfiling feature flag. * Add functions that call User Timing APIs to a new SchedulingProfiler file. The file follows DebugTracing's structure. * Add user timing marks to places where DebugTracing logs. * Add user timing marks to most other places where @bvaughn's original draft DebugTracing branch marks. * Tests added * More context (and discussions with @bvaughn) available at our internal PR MLH-Fellowship#11 and issue MLH-Fellowship#5. Similar to DebugTracing, we've only added scheduling profiling calls to the old reconciler fork. Co-authored-by: Kartik Choudhary <kartik.c918@gmail.com> Co-authored-by: Kartik Choudhary <kartikc.918@gmail.com> Co-authored-by: Brian Vaughn <brian.david.vaughn@gmail.com>
1 parent b85b476 commit 40cddfe

16 files changed

+772
-5
lines changed

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
debugRenderPhaseSideEffectsForStrictMode,
1818
disableLegacyContext,
1919
enableDebugTracing,
20+
enableSchedulingProfiler,
2021
warnAboutDeprecatedLifecycles,
2122
} from 'shared/ReactFeatureFlags';
2223
import ReactStrictModeWarnings from './ReactStrictModeWarnings.old';
@@ -59,6 +60,10 @@ import {requestCurrentSuspenseConfig} from './ReactFiberSuspenseConfig';
5960
import {logForceUpdateScheduled, logStateUpdateScheduled} from './DebugTracing';
6061

6162
import {disableLogs, reenableLogs} from 'shared/ConsolePatchingDev';
63+
import {
64+
markForceUpdateScheduled,
65+
markStateUpdateScheduled,
66+
} from './SchedulingProfiler';
6267

6368
const fakeInternalInstance = {};
6469
const isArray = Array.isArray;
@@ -214,6 +219,10 @@ const classComponentUpdater = {
214219
}
215220
}
216221
}
222+
223+
if (enableSchedulingProfiler) {
224+
markStateUpdateScheduled(fiber, lane);
225+
}
217226
},
218227
enqueueReplaceState(inst, payload, callback) {
219228
const fiber = getInstance(inst);
@@ -243,6 +252,10 @@ const classComponentUpdater = {
243252
}
244253
}
245254
}
255+
256+
if (enableSchedulingProfiler) {
257+
markStateUpdateScheduled(fiber, lane);
258+
}
246259
},
247260
enqueueForceUpdate(inst, callback) {
248261
const fiber = getInstance(inst);
@@ -271,6 +284,10 @@ const classComponentUpdater = {
271284
}
272285
}
273286
}
287+
288+
if (enableSchedulingProfiler) {
289+
markForceUpdateScheduled(fiber, lane);
290+
}
274291
},
275292
};
276293

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import type {OpaqueIDType} from './ReactFiberHostConfig';
2626
import ReactSharedInternals from 'shared/ReactSharedInternals';
2727
import {
2828
enableDebugTracing,
29+
enableSchedulingProfiler,
2930
enableNewReconciler,
3031
} from 'shared/ReactFeatureFlags';
3132

@@ -92,6 +93,7 @@ import {
9293
} from './ReactMutableSource.old';
9394
import {getIsRendering} from './ReactCurrentFiber';
9495
import {logStateUpdateScheduled} from './DebugTracing';
96+
import {markStateUpdateScheduled} from './SchedulingProfiler';
9597

9698
const {ReactCurrentDispatcher, ReactCurrentBatchConfig} = ReactSharedInternals;
9799

@@ -1764,6 +1766,10 @@ function dispatchAction<S, A>(
17641766
}
17651767
}
17661768
}
1769+
1770+
if (enableSchedulingProfiler) {
1771+
markStateUpdateScheduled(fiber, lane);
1772+
}
17671773
}
17681774

17691775
export const ContextOnlyDispatcher: Dispatcher = {

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import {
3939
} from './ReactWorkTags';
4040
import getComponentName from 'shared/getComponentName';
4141
import invariant from 'shared/invariant';
42+
import {enableSchedulingProfiler} from 'shared/ReactFeatureFlags';
4243
import ReactSharedInternals from 'shared/ReactSharedInternals';
4344
import {getPublicInstance} from './ReactFiberHostConfig';
4445
import {
@@ -95,6 +96,7 @@ import {
9596
setRefreshHandler,
9697
findHostInstancesForRefresh,
9798
} from './ReactFiberHotReloading.old';
99+
import {markRenderScheduled} from './SchedulingProfiler';
98100

99101
export {registerMutableSourceForHydration} from './ReactMutableSource.new';
100102
export {createPortal} from './ReactPortal';
@@ -273,6 +275,10 @@ export function updateContainer(
273275
const suspenseConfig = requestCurrentSuspenseConfig();
274276
const lane = requestUpdateLane(current, suspenseConfig);
275277

278+
if (enableSchedulingProfiler) {
279+
markRenderScheduled(lane);
280+
}
281+
276282
const context = getContextForSubtree(parentComponent);
277283
if (container.context === null) {
278284
container.context = context;

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@ import {
3232
} from './ReactSideEffectTags';
3333
import {shouldCaptureSuspense} from './ReactFiberSuspenseComponent.old';
3434
import {NoMode, BlockingMode, DebugTracingMode} from './ReactTypeOfMode';
35-
import {enableDebugTracing} from 'shared/ReactFeatureFlags';
35+
import {
36+
enableDebugTracing,
37+
enableSchedulingProfiler,
38+
} from 'shared/ReactFeatureFlags';
3639
import {createCapturedValue} from './ReactCapturedValue';
3740
import {
3841
enqueueCapturedUpdate,
@@ -56,6 +59,7 @@ import {
5659
} from './ReactFiberWorkLoop.old';
5760
import {logCapturedError} from './ReactFiberErrorLogger';
5861
import {logComponentSuspended} from './DebugTracing';
62+
import {markComponentSuspended} from './SchedulingProfiler';
5963

6064
import {
6165
SyncLane,
@@ -201,6 +205,10 @@ function throwException(
201205
}
202206
}
203207

208+
if (enableSchedulingProfiler) {
209+
markComponentSuspended(sourceFiber, wakeable);
210+
}
211+
204212
if ((sourceFiber.mode & BlockingMode) === NoMode) {
205213
// Reset the memoizedState to what it was before we attempted
206214
// to render it.

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

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import {
2828
deferRenderPhaseUpdateToNextBatch,
2929
decoupleUpdatePriorityFromScheduler,
3030
enableDebugTracing,
31+
enableSchedulingProfiler,
3132
} from 'shared/ReactFeatureFlags';
3233
import ReactSharedInternals from 'shared/ReactSharedInternals';
3334
import invariant from 'shared/invariant';
@@ -57,6 +58,17 @@ import {
5758
logRenderStarted,
5859
logRenderStopped,
5960
} from './DebugTracing';
61+
import {
62+
markCommitStarted,
63+
markCommitStopped,
64+
markLayoutEffectsStarted,
65+
markLayoutEffectsStopped,
66+
markPassiveEffectsStarted,
67+
markPassiveEffectsStopped,
68+
markRenderStarted,
69+
markRenderYielded,
70+
markRenderStopped,
71+
} from './SchedulingProfiler';
6072

6173
// The scheduler is imported here *only* to detect whether it's been mocked
6274
import * as Scheduler from 'scheduler';
@@ -1509,6 +1521,10 @@ function renderRootSync(root: FiberRoot, lanes: Lanes) {
15091521
}
15101522
}
15111523

1524+
if (enableSchedulingProfiler) {
1525+
markRenderStarted(lanes);
1526+
}
1527+
15121528
do {
15131529
try {
15141530
workLoopSync();
@@ -1540,6 +1556,10 @@ function renderRootSync(root: FiberRoot, lanes: Lanes) {
15401556
}
15411557
}
15421558

1559+
if (enableSchedulingProfiler) {
1560+
markRenderStopped();
1561+
}
1562+
15431563
// Set this to null to indicate there's no in-progress render.
15441564
workInProgressRoot = null;
15451565
workInProgressRootRenderLanes = NoLanes;
@@ -1576,6 +1596,10 @@ function renderRootConcurrent(root: FiberRoot, lanes: Lanes) {
15761596
}
15771597
}
15781598

1599+
if (enableSchedulingProfiler) {
1600+
markRenderStarted(lanes);
1601+
}
1602+
15791603
do {
15801604
try {
15811605
workLoopConcurrent();
@@ -1601,9 +1625,16 @@ function renderRootConcurrent(root: FiberRoot, lanes: Lanes) {
16011625
// Check if the tree has completed.
16021626
if (workInProgress !== null) {
16031627
// Still work remaining.
1628+
if (enableSchedulingProfiler) {
1629+
markRenderYielded();
1630+
}
16041631
return RootIncomplete;
16051632
} else {
16061633
// Completed the tree.
1634+
if (enableSchedulingProfiler) {
1635+
markRenderStopped();
1636+
}
1637+
16071638
// Set this to null to indicate there's no in-progress render.
16081639
workInProgressRoot = null;
16091640
workInProgressRootRenderLanes = NoLanes;
@@ -1893,13 +1924,21 @@ function commitRootImpl(root, renderPriorityLevel) {
18931924
}
18941925
}
18951926

1927+
if (enableSchedulingProfiler) {
1928+
markCommitStarted(lanes);
1929+
}
1930+
18961931
if (finishedWork === null) {
18971932
if (__DEV__) {
18981933
if (enableDebugTracing) {
18991934
logCommitStopped();
19001935
}
19011936
}
19021937

1938+
if (enableSchedulingProfiler) {
1939+
markCommitStopped();
1940+
}
1941+
19031942
return null;
19041943
}
19051944
root.finishedWork = null;
@@ -2196,6 +2235,10 @@ function commitRootImpl(root, renderPriorityLevel) {
21962235
}
21972236
}
21982237

2238+
if (enableSchedulingProfiler) {
2239+
markCommitStopped();
2240+
}
2241+
21992242
// This is a legacy edge case. We just committed the initial mount of
22002243
// a ReactDOM.render-ed root inside of batchedUpdates. The commit fired
22012244
// synchronously, but layout updates should be deferred until the end
@@ -2212,6 +2255,10 @@ function commitRootImpl(root, renderPriorityLevel) {
22122255
}
22132256
}
22142257

2258+
if (enableSchedulingProfiler) {
2259+
markCommitStopped();
2260+
}
2261+
22152262
return null;
22162263
}
22172264

@@ -2342,6 +2389,10 @@ function commitLayoutEffects(root: FiberRoot, committedLanes: Lanes) {
23422389
}
23432390
}
23442391

2392+
if (enableSchedulingProfiler) {
2393+
markLayoutEffectsStarted(committedLanes);
2394+
}
2395+
23452396
// TODO: Should probably move the bulk of this function to commitWork.
23462397
while (nextEffect !== null) {
23472398
setCurrentDebugFiberInDEV(nextEffect);
@@ -2366,6 +2417,10 @@ function commitLayoutEffects(root: FiberRoot, committedLanes: Lanes) {
23662417
logLayoutEffectsStopped();
23672418
}
23682419
}
2420+
2421+
if (enableSchedulingProfiler) {
2422+
markLayoutEffectsStopped();
2423+
}
23692424
}
23702425

23712426
export function flushPassiveEffects() {
@@ -2461,6 +2516,10 @@ function flushPassiveEffectsImpl() {
24612516
}
24622517
}
24632518

2519+
if (enableSchedulingProfiler) {
2520+
markPassiveEffectsStarted(lanes);
2521+
}
2522+
24642523
if (__DEV__) {
24652524
isFlushingPassiveEffects = true;
24662525
}
@@ -2623,6 +2682,10 @@ function flushPassiveEffectsImpl() {
26232682
}
26242683
}
26252684

2685+
if (enableSchedulingProfiler) {
2686+
markPassiveEffectsStopped();
2687+
}
2688+
26262689
executionContext = prevExecutionContext;
26272690

26282691
flushSyncCallbackQueue();

0 commit comments

Comments
 (0)