Skip to content

Commit

Permalink
Add user timing marks for scheduling profiler tool (#19223)
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
4 people authored Jul 8, 2020
1 parent b85b476 commit 40cddfe
Show file tree
Hide file tree
Showing 16 changed files with 772 additions and 5 deletions.
17 changes: 17 additions & 0 deletions packages/react-reconciler/src/ReactFiberClassComponent.old.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
debugRenderPhaseSideEffectsForStrictMode,
disableLegacyContext,
enableDebugTracing,
enableSchedulingProfiler,
warnAboutDeprecatedLifecycles,
} from 'shared/ReactFeatureFlags';
import ReactStrictModeWarnings from './ReactStrictModeWarnings.old';
Expand Down Expand Up @@ -59,6 +60,10 @@ import {requestCurrentSuspenseConfig} from './ReactFiberSuspenseConfig';
import {logForceUpdateScheduled, logStateUpdateScheduled} from './DebugTracing';

import {disableLogs, reenableLogs} from 'shared/ConsolePatchingDev';
import {
markForceUpdateScheduled,
markStateUpdateScheduled,
} from './SchedulingProfiler';

const fakeInternalInstance = {};
const isArray = Array.isArray;
Expand Down Expand Up @@ -214,6 +219,10 @@ const classComponentUpdater = {
}
}
}

if (enableSchedulingProfiler) {
markStateUpdateScheduled(fiber, lane);
}
},
enqueueReplaceState(inst, payload, callback) {
const fiber = getInstance(inst);
Expand Down Expand Up @@ -243,6 +252,10 @@ const classComponentUpdater = {
}
}
}

if (enableSchedulingProfiler) {
markStateUpdateScheduled(fiber, lane);
}
},
enqueueForceUpdate(inst, callback) {
const fiber = getInstance(inst);
Expand Down Expand Up @@ -271,6 +284,10 @@ const classComponentUpdater = {
}
}
}

if (enableSchedulingProfiler) {
markForceUpdateScheduled(fiber, lane);
}
},
};

Expand Down
6 changes: 6 additions & 0 deletions packages/react-reconciler/src/ReactFiberHooks.old.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import type {OpaqueIDType} from './ReactFiberHostConfig';
import ReactSharedInternals from 'shared/ReactSharedInternals';
import {
enableDebugTracing,
enableSchedulingProfiler,
enableNewReconciler,
} from 'shared/ReactFeatureFlags';

Expand Down Expand Up @@ -92,6 +93,7 @@ import {
} from './ReactMutableSource.old';
import {getIsRendering} from './ReactCurrentFiber';
import {logStateUpdateScheduled} from './DebugTracing';
import {markStateUpdateScheduled} from './SchedulingProfiler';

const {ReactCurrentDispatcher, ReactCurrentBatchConfig} = ReactSharedInternals;

Expand Down Expand Up @@ -1764,6 +1766,10 @@ function dispatchAction<S, A>(
}
}
}

if (enableSchedulingProfiler) {
markStateUpdateScheduled(fiber, lane);
}
}

export const ContextOnlyDispatcher: Dispatcher = {
Expand Down
6 changes: 6 additions & 0 deletions packages/react-reconciler/src/ReactFiberReconciler.old.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import {
} from './ReactWorkTags';
import getComponentName from 'shared/getComponentName';
import invariant from 'shared/invariant';
import {enableSchedulingProfiler} from 'shared/ReactFeatureFlags';
import ReactSharedInternals from 'shared/ReactSharedInternals';
import {getPublicInstance} from './ReactFiberHostConfig';
import {
Expand Down Expand Up @@ -95,6 +96,7 @@ import {
setRefreshHandler,
findHostInstancesForRefresh,
} from './ReactFiberHotReloading.old';
import {markRenderScheduled} from './SchedulingProfiler';

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

if (enableSchedulingProfiler) {
markRenderScheduled(lane);
}

const context = getContextForSubtree(parentComponent);
if (container.context === null) {
container.context = context;
Expand Down
10 changes: 9 additions & 1 deletion packages/react-reconciler/src/ReactFiberThrow.old.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ import {
} from './ReactSideEffectTags';
import {shouldCaptureSuspense} from './ReactFiberSuspenseComponent.old';
import {NoMode, BlockingMode, DebugTracingMode} from './ReactTypeOfMode';
import {enableDebugTracing} from 'shared/ReactFeatureFlags';
import {
enableDebugTracing,
enableSchedulingProfiler,
} from 'shared/ReactFeatureFlags';
import {createCapturedValue} from './ReactCapturedValue';
import {
enqueueCapturedUpdate,
Expand All @@ -56,6 +59,7 @@ import {
} from './ReactFiberWorkLoop.old';
import {logCapturedError} from './ReactFiberErrorLogger';
import {logComponentSuspended} from './DebugTracing';
import {markComponentSuspended} from './SchedulingProfiler';

import {
SyncLane,
Expand Down Expand Up @@ -201,6 +205,10 @@ function throwException(
}
}

if (enableSchedulingProfiler) {
markComponentSuspended(sourceFiber, wakeable);
}

if ((sourceFiber.mode & BlockingMode) === NoMode) {
// Reset the memoizedState to what it was before we attempted
// to render it.
Expand Down
63 changes: 63 additions & 0 deletions packages/react-reconciler/src/ReactFiberWorkLoop.old.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
deferRenderPhaseUpdateToNextBatch,
decoupleUpdatePriorityFromScheduler,
enableDebugTracing,
enableSchedulingProfiler,
} from 'shared/ReactFeatureFlags';
import ReactSharedInternals from 'shared/ReactSharedInternals';
import invariant from 'shared/invariant';
Expand Down Expand Up @@ -57,6 +58,17 @@ import {
logRenderStarted,
logRenderStopped,
} from './DebugTracing';
import {
markCommitStarted,
markCommitStopped,
markLayoutEffectsStarted,
markLayoutEffectsStopped,
markPassiveEffectsStarted,
markPassiveEffectsStopped,
markRenderStarted,
markRenderYielded,
markRenderStopped,
} from './SchedulingProfiler';

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

if (enableSchedulingProfiler) {
markRenderStarted(lanes);
}

do {
try {
workLoopSync();
Expand Down Expand Up @@ -1540,6 +1556,10 @@ function renderRootSync(root: FiberRoot, lanes: Lanes) {
}
}

if (enableSchedulingProfiler) {
markRenderStopped();
}

// Set this to null to indicate there's no in-progress render.
workInProgressRoot = null;
workInProgressRootRenderLanes = NoLanes;
Expand Down Expand Up @@ -1576,6 +1596,10 @@ function renderRootConcurrent(root: FiberRoot, lanes: Lanes) {
}
}

if (enableSchedulingProfiler) {
markRenderStarted(lanes);
}

do {
try {
workLoopConcurrent();
Expand All @@ -1601,9 +1625,16 @@ function renderRootConcurrent(root: FiberRoot, lanes: Lanes) {
// Check if the tree has completed.
if (workInProgress !== null) {
// Still work remaining.
if (enableSchedulingProfiler) {
markRenderYielded();
}
return RootIncomplete;
} else {
// Completed the tree.
if (enableSchedulingProfiler) {
markRenderStopped();
}

// Set this to null to indicate there's no in-progress render.
workInProgressRoot = null;
workInProgressRootRenderLanes = NoLanes;
Expand Down Expand Up @@ -1893,13 +1924,21 @@ function commitRootImpl(root, renderPriorityLevel) {
}
}

if (enableSchedulingProfiler) {
markCommitStarted(lanes);
}

if (finishedWork === null) {
if (__DEV__) {
if (enableDebugTracing) {
logCommitStopped();
}
}

if (enableSchedulingProfiler) {
markCommitStopped();
}

return null;
}
root.finishedWork = null;
Expand Down Expand Up @@ -2196,6 +2235,10 @@ function commitRootImpl(root, renderPriorityLevel) {
}
}

if (enableSchedulingProfiler) {
markCommitStopped();
}

// This is a legacy edge case. We just committed the initial mount of
// a ReactDOM.render-ed root inside of batchedUpdates. The commit fired
// synchronously, but layout updates should be deferred until the end
Expand All @@ -2212,6 +2255,10 @@ function commitRootImpl(root, renderPriorityLevel) {
}
}

if (enableSchedulingProfiler) {
markCommitStopped();
}

return null;
}

Expand Down Expand Up @@ -2342,6 +2389,10 @@ function commitLayoutEffects(root: FiberRoot, committedLanes: Lanes) {
}
}

if (enableSchedulingProfiler) {
markLayoutEffectsStarted(committedLanes);
}

// TODO: Should probably move the bulk of this function to commitWork.
while (nextEffect !== null) {
setCurrentDebugFiberInDEV(nextEffect);
Expand All @@ -2366,6 +2417,10 @@ function commitLayoutEffects(root: FiberRoot, committedLanes: Lanes) {
logLayoutEffectsStopped();
}
}

if (enableSchedulingProfiler) {
markLayoutEffectsStopped();
}
}

export function flushPassiveEffects() {
Expand Down Expand Up @@ -2461,6 +2516,10 @@ function flushPassiveEffectsImpl() {
}
}

if (enableSchedulingProfiler) {
markPassiveEffectsStarted(lanes);
}

if (__DEV__) {
isFlushingPassiveEffects = true;
}
Expand Down Expand Up @@ -2623,6 +2682,10 @@ function flushPassiveEffectsImpl() {
}
}

if (enableSchedulingProfiler) {
markPassiveEffectsStopped();
}

executionContext = prevExecutionContext;

flushSyncCallbackQueue();
Expand Down
Loading

0 comments on commit 40cddfe

Please sign in to comment.