Skip to content

Commit

Permalink
Pass "start time" and "commit time" to Profiler callback (facebook#12852
Browse files Browse the repository at this point in the history
)

* Added start time parameter to Profiler onRender callback
* Profiler also captures commit time
* Only init Profiler stateNode if enableProfilerTimer feature flag enabled
  • Loading branch information
bvaughn authored May 21, 2018
1 parent 12c8a88 commit 1300365
Show file tree
Hide file tree
Showing 5 changed files with 229 additions and 96 deletions.
11 changes: 7 additions & 4 deletions packages/react-reconciler/src/ReactFiber.js
Original file line number Diff line number Diff line change
Expand Up @@ -460,10 +460,13 @@ export function createFiberFromProfiler(
const fiber = createFiber(Profiler, pendingProps, key, mode | ProfileMode);
fiber.type = REACT_PROFILER_TYPE;
fiber.expirationTime = expirationTime;
fiber.stateNode = {
duration: 0,
startTime: 0,
};
if (enableProfilerTimer) {
fiber.stateNode = {
elapsedPauseTimeAtStart: 0,
duration: 0,
startTime: 0,
};
}

return fiber;
}
Expand Down
3 changes: 3 additions & 0 deletions packages/react-reconciler/src/ReactFiberCommitWork.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import type {ExpirationTime} from './ReactFiberExpirationTime';
import type {CapturedValue, CapturedError} from './ReactCapturedValue';

import {enableProfilerTimer} from 'shared/ReactFeatureFlags';
import {getCommitTime} from './ReactProfilerTimer';
import {
ClassComponent,
HostRoot,
Expand Down Expand Up @@ -807,6 +808,8 @@ function commitWork(current: Fiber | null, finishedWork: Fiber): void {
current === null ? 'mount' : 'update',
finishedWork.stateNode.duration,
finishedWork.treeBaseTime,
finishedWork.stateNode.startTime,
getCommitTime(),
);

// Reset actualTime after successful commit.
Expand Down
5 changes: 5 additions & 0 deletions packages/react-reconciler/src/ReactFiberScheduler.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ import {popHostContext, popHostContainer} from './ReactFiberHostContext';
import {
checkActualRenderTimeStackEmpty,
pauseActualRenderTimerIfRunning,
recordCommitTime,
recordElapsedBaseRenderTimeIfRunning,
resetActualRenderTimer,
resumeActualRenderTimerIfPaused,
Expand Down Expand Up @@ -566,6 +567,10 @@ function commitRoot(finishedWork: Fiber): ExpirationTime {
}
stopCommitSnapshotEffectsTimer();

if (enableProfilerTimer) {
recordCommitTime();
}

// Commit all the side-effects within a tree. We'll do this in two passes.
// The first pass performs all the host insertions, updates, deletions and
// ref unmounts.
Expand Down
42 changes: 32 additions & 10 deletions packages/react-reconciler/src/ReactProfilerTimer.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,40 @@ import {enableProfilerTimer} from 'shared/ReactFeatureFlags';
import warning from 'fbjs/lib/warning';
import {now} from './ReactFiberHostConfig';

/**
* The "actual" render time is total time required to render the descendants of a Profiler component.
* This time is stored as a stack, since Profilers can be nested.
* This time is started during the "begin" phase and stopped during the "complete" phase.
* It is paused (and accumulated) in the event of an interruption or an aborted render.
*/

export type ProfilerTimer = {
checkActualRenderTimeStackEmpty(): void,
getCommitTime(): number,
markActualRenderTimeStarted(fiber: Fiber): void,
pauseActualRenderTimerIfRunning(): void,
recordElapsedActualRenderTime(fiber: Fiber): void,
resetActualRenderTimer(): void,
resumeActualRenderTimerIfPaused(): void,
recordCommitTime(): void,
recordElapsedBaseRenderTimeIfRunning(fiber: Fiber): void,
startBaseRenderTimer(): void,
stopBaseRenderTimerIfRunning(): void,
};

let commitTime: number = 0;

function getCommitTime(): number {
return commitTime;
}

function recordCommitTime(): void {
if (!enableProfilerTimer) {
return;
}
commitTime = now();
}

/**
* The "actual" render time is total time required to render the descendants of a Profiler component.
* This time is stored as a stack, since Profilers can be nested.
* This time is started during the "begin" phase and stopped during the "complete" phase.
* It is paused (and accumulated) in the event of an interruption or an aborted render.
*/

let fiberStack: Array<Fiber | null>;

if (__DEV__) {
Expand Down Expand Up @@ -61,7 +76,9 @@ function markActualRenderTimeStarted(fiber: Fiber): void {
if (__DEV__) {
fiberStack.push(fiber);
}
fiber.stateNode.startTime = now() - totalElapsedPauseTime;
const stateNode = fiber.stateNode;
stateNode.elapsedPauseTimeAtStart = totalElapsedPauseTime;
stateNode.startTime = now();
}

function pauseActualRenderTimerIfRunning(): void {
Expand All @@ -80,8 +97,11 @@ function recordElapsedActualRenderTime(fiber: Fiber): void {
if (__DEV__) {
warning(fiber === fiberStack.pop(), 'Unexpected Fiber popped.');
}
fiber.stateNode.duration +=
now() - totalElapsedPauseTime - fiber.stateNode.startTime;
const stateNode = fiber.stateNode;
stateNode.duration +=
now() -
(totalElapsedPauseTime - stateNode.elapsedPauseTimeAtStart) -
stateNode.startTime;
}

function resetActualRenderTimer(): void {
Expand Down Expand Up @@ -145,8 +165,10 @@ function stopBaseRenderTimerIfRunning(): void {

export {
checkActualRenderTimeStackEmpty,
getCommitTime,
markActualRenderTimeStarted,
pauseActualRenderTimerIfRunning,
recordCommitTime,
recordElapsedActualRenderTime,
resetActualRenderTimer,
resumeActualRenderTimerIfPaused,
Expand Down
Loading

0 comments on commit 1300365

Please sign in to comment.