-
Notifications
You must be signed in to change notification settings - Fork 47k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Fiber] Log Component Renders to Custom Performance Track (#30967)
Stacked on #30960 and #30966. Behind the enableComponentPerformanceTrack flag. This is the first step of performance logging. This logs the start and end time of a component render in the passive effect phase. We use the data we're already tracking on components when the Profiler component or DevTools is active in the Profiling or Dev builds. By backdating this after committing we avoid adding more overhead in the hot path. By only logging things that actually committed, we avoid the costly unwinding of an interrupted render which was hard to maintain in earlier versions. We already have the start time but we don't have the end time. That's because `actualStartTime + actualDuration` isn't enough since `actualDuration` counts the actual CPU time excluding yields and suspending in the render. Instead, we infer the end time to be the start time of the next sibling or the complete time of the whole root if there are no more siblings. We need to pass this down the passive effect tree. This will mean that any overhead and yields are attributed to this component's span. In a follow up, we'll need to start logging these yields to make it clear that this is not part of the component's self-time. In follow ups, I'll do the same for commit phases. We'll also need to log more information about the phases in the top track. We'll also need to filter out more components from the trees that we don't need to highlight like the internal Offscreen components. It also needs polish on colors etc. Currently, I place the components into separate tracks depending on which lane currently committed. That way you can see what was blocking Transitions or Suspense etc. One problem that I've hit with the new performance.measure extensions is that these tracks show up in the order they're used which is not the order of priority that we use. Even when you add fake markers they have to actually be within the performance run since otherwise the calls are noops so it's not enough to do that once. However, I think this visualization is actually not good because these trees end up so large that you can't see any other lanes once you expand one. Therefore, I think in a follow up I'll actually instead switch to a model where Components is a single track regardless of lane since we don't currently have overlap anyway. Then the description about what is actually rendering can be separate lanes. <img width="1512" alt="Screenshot 2024-09-15 at 10 55 55 PM" src="https://github.com/user-attachments/assets/5ca3fa74-97ce-40c7-97f7-80c1dd7d6470"> <img width="1512" alt="Screenshot 2024-09-15 at 10 56 27 PM" src="https://github.com/user-attachments/assets/557ad65b-4190-465f-843c-0bc6cbb9326d">
- Loading branch information
1 parent
ee1a403
commit f2df569
Showing
7 changed files
with
285 additions
and
49 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
61 changes: 61 additions & 0 deletions
61
packages/react-reconciler/src/ReactFiberPerformanceTrack.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
/** | ||
* Copyright (c) Meta Platforms, Inc. and affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
* | ||
* @flow | ||
*/ | ||
|
||
import type {Fiber} from './ReactInternalTypes'; | ||
|
||
import getComponentNameFromFiber from './getComponentNameFromFiber'; | ||
|
||
import {getGroupNameOfHighestPriorityLane} from './ReactFiberLane'; | ||
|
||
import {enableProfilerTimer} from 'shared/ReactFeatureFlags'; | ||
|
||
const supportsUserTiming = | ||
enableProfilerTimer && | ||
typeof performance !== 'undefined' && | ||
// $FlowFixMe[method-unbinding] | ||
typeof performance.measure === 'function'; | ||
|
||
const TRACK_GROUP = 'Components ⚛'; | ||
|
||
// Reused to avoid thrashing the GC. | ||
const reusableComponentDevToolDetails = { | ||
dataType: 'track-entry', | ||
color: 'primary', | ||
track: 'Blocking', // Lane | ||
trackGroup: TRACK_GROUP, | ||
}; | ||
const reusableComponentOptions = { | ||
start: -0, | ||
end: -0, | ||
detail: { | ||
devtools: reusableComponentDevToolDetails, | ||
}, | ||
}; | ||
|
||
export function setCurrentTrackFromLanes(lanes: number): void { | ||
reusableComponentDevToolDetails.track = | ||
getGroupNameOfHighestPriorityLane(lanes); | ||
} | ||
|
||
export function logComponentRender( | ||
fiber: Fiber, | ||
startTime: number, | ||
endTime: number, | ||
): void { | ||
const name = getComponentNameFromFiber(fiber); | ||
if (name === null) { | ||
// Skip | ||
return; | ||
} | ||
if (supportsUserTiming) { | ||
reusableComponentOptions.start = startTime; | ||
reusableComponentOptions.end = endTime; | ||
performance.measure(name, reusableComponentOptions); | ||
} | ||
} |
Oops, something went wrong.