diff --git a/packages/react-reconciler/src/ReactFiberPerformanceTrack.js b/packages/react-reconciler/src/ReactFiberPerformanceTrack.js index 04e586314293d..56470bb0e55d6 100644 --- a/packages/react-reconciler/src/ReactFiberPerformanceTrack.js +++ b/packages/react-reconciler/src/ReactFiberPerformanceTrack.js @@ -25,7 +25,6 @@ const COMPONENTS_TRACK = 'Components ⚛'; // Reused to avoid thrashing the GC. const reusableComponentDevToolDetails = { - dataType: 'track-entry', color: 'primary', track: COMPONENTS_TRACK, }; @@ -40,7 +39,6 @@ const reusableComponentOptions = { const LANES_TRACK_GROUP = 'Scheduler ⚛'; const reusableLaneDevToolDetails = { - dataType: 'track-entry', color: 'primary', track: 'Blocking', // Lane trackGroup: LANES_TRACK_GROUP, @@ -57,6 +55,63 @@ export function setCurrentTrackFromLanes(lanes: number): void { reusableLaneDevToolDetails.track = getGroupNameOfHighestPriorityLane(lanes); } +const blockingLaneMarker = { + startTime: 0, + detail: { + devtools: { + color: 'primary-light', + track: 'Blocking', + trackGroup: LANES_TRACK_GROUP, + }, + }, +}; + +const transitionLaneMarker = { + startTime: 0, + detail: { + devtools: { + color: 'primary-light', + track: 'Transition', + trackGroup: LANES_TRACK_GROUP, + }, + }, +}; + +const suspenseLaneMarker = { + startTime: 0, + detail: { + devtools: { + color: 'primary-light', + track: 'Suspense', + trackGroup: LANES_TRACK_GROUP, + }, + }, +}; + +const idleLaneMarker = { + startTime: 0, + detail: { + devtools: { + color: 'primary-light', + track: 'Idle', + trackGroup: LANES_TRACK_GROUP, + }, + }, +}; + +export function markAllLanesInOrder() { + if (supportsUserTiming) { + // Ensure we create all tracks in priority order. Currently performance.mark() are in + // first insertion order but performance.measure() are in the reverse order. We can + // always add the 0 time slot even if it's in the past. That's still considered for + // ordering. + performance.mark('Blocking Track', blockingLaneMarker); + performance.mark('Transition Track', transitionLaneMarker); + performance.mark('Suspense Track', suspenseLaneMarker); + performance.mark('Idle Track', idleLaneMarker); + } +} + export function logComponentRender( fiber: Fiber, startTime: number, diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.js b/packages/react-reconciler/src/ReactFiberWorkLoop.js index 2ff35b0c6a7f2..f812d16c9c65a 100644 --- a/packages/react-reconciler/src/ReactFiberWorkLoop.js +++ b/packages/react-reconciler/src/ReactFiberWorkLoop.js @@ -82,6 +82,8 @@ import { logYieldTime, logActionYieldTime, logSuspendedYieldTime, + setCurrentTrackFromLanes, + markAllLanesInOrder, } from './ReactFiberPerformanceTrack'; import { @@ -271,7 +273,6 @@ import { yieldReason, startPingTimerByLanes, } from './ReactProfilerTimer'; -import {setCurrentTrackFromLanes} from './ReactFiberPerformanceTrack'; // DEV stuff import getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFromFiber'; @@ -1727,6 +1728,15 @@ function finalizeRender(lanes: Lanes, finalizationTime: number): void { function prepareFreshStack(root: FiberRoot, lanes: Lanes): Fiber { if (enableProfilerTimer && enableComponentPerformanceTrack) { + // The order of tracks within a group are determined by the earliest start time. + // Are tracks should show up in priority order and we should ideally always show + // every track. This is a hack to ensure that we're displaying all tracks in the + // right order. Ideally we could do this only once but because calls that aren't + // recorded aren't considered for ordering purposes, we need to keep adding these + // over and over again in case recording has just started. We can't tell when + // recording starts. + markAllLanesInOrder(); + const previousRenderStartTime = renderStartTime; // Starting a new render. Log the end of any previous renders and the // blocked time before the render started.