diff --git a/packages/react-devtools-shared/src/__tests__/__snapshots__/profilingCache-test.js.snap b/packages/react-devtools-shared/src/__tests__/__snapshots__/profilingCache-test.js.snap index a47598e92d522..c9e7f9770159f 100644 --- a/packages/react-devtools-shared/src/__tests__/__snapshots__/profilingCache-test.js.snap +++ b/packages/react-devtools-shared/src/__tests__/__snapshots__/profilingCache-test.js.snap @@ -26,6 +26,7 @@ Object { }, }, "duration": 16, + "effectDuration": null, "fiberActualDurations": Map { 1 => 16, 2 => 16, @@ -39,6 +40,7 @@ Object { 5 => 1, }, "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Normal", "timestamp": 16, } @@ -63,6 +65,7 @@ Object { }, }, "duration": 15, + "effectDuration": null, "fiberActualDurations": Map { 1 => 15, 2 => 15, @@ -76,6 +79,7 @@ Object { 4 => 2, }, "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Normal", "timestamp": 15, } @@ -93,6 +97,7 @@ Object { }, }, "duration": 3, + "effectDuration": null, "fiberActualDurations": Map { 5 => 3, 3 => 3, @@ -102,6 +107,7 @@ Object { 3 => 0, }, "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Immediate", "timestamp": 18, } @@ -140,6 +146,7 @@ Object { }, }, "duration": 12, + "effectDuration": null, "fiberActualDurations": Map { 1 => 12, 2 => 12, @@ -155,6 +162,7 @@ Object { 5 => 1, }, "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Normal", "timestamp": 12, } @@ -195,6 +203,7 @@ Object { }, }, "duration": 13, + "effectDuration": null, "fiberActualDurations": Map { 3 => 0, 4 => 1, @@ -210,6 +219,7 @@ Object { 1 => 0, }, "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Immediate", "timestamp": 25, } @@ -236,6 +246,7 @@ Object { }, }, "duration": 10, + "effectDuration": null, "fiberActualDurations": Map { 3 => 0, 2 => 10, @@ -247,6 +258,7 @@ Object { 1 => 0, }, "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Immediate", "timestamp": 35, } @@ -266,6 +278,7 @@ Object { }, }, "duration": 10, + "effectDuration": null, "fiberActualDurations": Map { 2 => 10, 1 => 10, @@ -275,6 +288,7 @@ Object { 1 => 0, }, "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Immediate", "timestamp": 45, } @@ -329,6 +343,7 @@ Object { ], ], "duration": 12, + "effectDuration": null, "fiberActualDurations": Array [ Array [ 1, @@ -374,6 +389,7 @@ Object { ], ], "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Normal", "timestamp": 12, }, @@ -423,6 +439,7 @@ Object { ], ], "duration": 13, + "effectDuration": null, "fiberActualDurations": Array [ Array [ 3, @@ -468,6 +485,7 @@ Object { ], ], "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Immediate", "timestamp": 25, }, @@ -497,6 +515,7 @@ Object { ], ], "duration": 10, + "effectDuration": null, "fiberActualDurations": Array [ Array [ 3, @@ -526,6 +545,7 @@ Object { ], ], "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Immediate", "timestamp": 35, }, @@ -545,6 +565,7 @@ Object { ], ], "duration": 10, + "effectDuration": null, "fiberActualDurations": Array [ Array [ 2, @@ -566,6 +587,7 @@ Object { ], ], "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Immediate", "timestamp": 45, }, @@ -792,6 +814,7 @@ Object { ], ], "duration": 11, + "effectDuration": null, "fiberActualDurations": Array [ Array [ 1, @@ -829,6 +852,7 @@ Object { ], ], "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Normal", "timestamp": 11, }, @@ -868,6 +892,7 @@ Object { ], ], "duration": 11, + "effectDuration": null, "fiberActualDurations": Array [ Array [ 3, @@ -905,6 +930,7 @@ Object { ], ], "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Immediate", "timestamp": 22, }, @@ -954,6 +980,7 @@ Object { ], ], "duration": 13, + "effectDuration": null, "fiberActualDurations": Array [ Array [ 3, @@ -999,6 +1026,7 @@ Object { ], ], "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Immediate", "timestamp": 35, }, @@ -1183,6 +1211,7 @@ Object { }, }, "duration": 13, + "effectDuration": null, "fiberActualDurations": Map { 3 => 0, 4 => 1, @@ -1198,6 +1227,7 @@ Object { 1 => 0, }, "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Immediate", "timestamp": 13, }, @@ -1221,6 +1251,7 @@ Object { }, }, "duration": 10, + "effectDuration": null, "fiberActualDurations": Map { 3 => 0, 2 => 10, @@ -1232,6 +1263,7 @@ Object { 1 => 0, }, "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Immediate", "timestamp": 34, }, @@ -1248,6 +1280,7 @@ Object { }, }, "duration": 10, + "effectDuration": null, "fiberActualDurations": Map { 2 => 10, 1 => 10, @@ -1257,6 +1290,7 @@ Object { 1 => 0, }, "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Immediate", "timestamp": 44, }, @@ -1419,6 +1453,7 @@ Object { }, }, "duration": 11, + "effectDuration": null, "fiberActualDurations": Map { 11 => 11, 12 => 11, @@ -1432,6 +1467,7 @@ Object { 14 => 1, }, "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Normal", "timestamp": 24, }, @@ -1511,9 +1547,11 @@ Object { Object { "changeDescriptions": Map {}, "duration": 0, + "effectDuration": null, "fiberActualDurations": Map {}, "fiberSelfDurations": Map {}, "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Normal", "timestamp": 34, }, @@ -1636,6 +1674,7 @@ Object { ], ], "duration": 13, + "effectDuration": null, "fiberActualDurations": Array [ Array [ 3, @@ -1681,6 +1720,7 @@ Object { ], ], "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Immediate", "timestamp": 13, }, @@ -1710,6 +1750,7 @@ Object { ], ], "duration": 10, + "effectDuration": null, "fiberActualDurations": Array [ Array [ 3, @@ -1739,6 +1780,7 @@ Object { ], ], "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Immediate", "timestamp": 34, }, @@ -1758,6 +1800,7 @@ Object { ], ], "duration": 10, + "effectDuration": null, "fiberActualDurations": Array [ Array [ 2, @@ -1779,6 +1822,7 @@ Object { ], ], "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Immediate", "timestamp": 44, }, @@ -1977,6 +2021,7 @@ Object { ], ], "duration": 11, + "effectDuration": null, "fiberActualDurations": Array [ Array [ 11, @@ -2014,6 +2059,7 @@ Object { ], ], "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Normal", "timestamp": 24, }, @@ -2090,9 +2136,11 @@ Object { Object { "changeDescriptions": Array [], "duration": 0, + "effectDuration": null, "fiberActualDurations": Array [], "fiberSelfDurations": Array [], "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Normal", "timestamp": 34, }, @@ -2197,6 +2245,7 @@ Object { Object { "changeDescriptions": Map {}, "duration": 0, + "effectDuration": null, "fiberActualDurations": Map { 1 => 0, 2 => 0, @@ -2206,6 +2255,7 @@ Object { 2 => 0, }, "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Normal", "timestamp": 0, }, @@ -2262,6 +2312,7 @@ Object { }, }, "duration": 0, + "effectDuration": null, "fiberActualDurations": Map { 1 => 0, 2 => 0, @@ -2273,6 +2324,7 @@ Object { 3 => 0, }, "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Normal", "timestamp": 0, } @@ -2292,6 +2344,7 @@ Object { }, }, "duration": 0, + "effectDuration": null, "fiberActualDurations": Map { 3 => 0, 2 => 0, @@ -2303,6 +2356,7 @@ Object { 1 => 0, }, "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Immediate", "timestamp": 0, } @@ -2320,6 +2374,7 @@ Object { }, }, "duration": 0, + "effectDuration": null, "fiberActualDurations": Map { 3 => 0, }, @@ -2327,6 +2382,7 @@ Object { 3 => 0, }, "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Immediate", "timestamp": 0, } @@ -2344,6 +2400,7 @@ Object { }, }, "duration": 0, + "effectDuration": null, "fiberActualDurations": Map { 3 => 0, }, @@ -2351,6 +2408,7 @@ Object { 3 => 0, }, "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Immediate", "timestamp": 0, } @@ -2368,6 +2426,7 @@ Object { }, }, "duration": 0, + "effectDuration": null, "fiberActualDurations": Map { 3 => 0, 2 => 0, @@ -2379,6 +2438,7 @@ Object { 1 => 0, }, "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Immediate", "timestamp": 0, } @@ -2403,6 +2463,7 @@ Object { ], ], "duration": 0, + "effectDuration": null, "fiberActualDurations": Array [ Array [ 1, @@ -2432,6 +2493,7 @@ Object { ], ], "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Normal", "timestamp": 0, }, @@ -2451,6 +2513,7 @@ Object { ], ], "duration": 0, + "effectDuration": null, "fiberActualDurations": Array [ Array [ 3, @@ -2480,6 +2543,7 @@ Object { ], ], "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Immediate", "timestamp": 0, }, @@ -2497,6 +2561,7 @@ Object { ], ], "duration": 0, + "effectDuration": null, "fiberActualDurations": Array [ Array [ 3, @@ -2510,6 +2575,7 @@ Object { ], ], "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Immediate", "timestamp": 0, }, @@ -2527,6 +2593,7 @@ Object { ], ], "duration": 0, + "effectDuration": null, "fiberActualDurations": Array [ Array [ 3, @@ -2540,6 +2607,7 @@ Object { ], ], "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Immediate", "timestamp": 0, }, @@ -2557,6 +2625,7 @@ Object { ], ], "duration": 0, + "effectDuration": null, "fiberActualDurations": Array [ Array [ 3, @@ -2586,6 +2655,7 @@ Object { ], ], "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Immediate", "timestamp": 0, }, @@ -2721,6 +2791,7 @@ Object { }, }, "duration": 0, + "effectDuration": null, "fiberActualDurations": Map { 1 => 0, 2 => 0, @@ -2740,6 +2811,7 @@ Object { 7 => 0, }, "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Normal", "timestamp": 0, } @@ -2793,6 +2865,7 @@ Object { }, }, "duration": 0, + "effectDuration": null, "fiberActualDurations": Map { 5 => 0, 4 => 0, @@ -2810,6 +2883,7 @@ Object { 2 => 0, }, "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Immediate", "timestamp": 0, } @@ -2857,6 +2931,7 @@ Object { }, }, "duration": 0, + "effectDuration": null, "fiberActualDurations": Map { 5 => 0, 4 => 0, @@ -2876,6 +2951,7 @@ Object { 1 => 0, }, "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Immediate", "timestamp": 0, } @@ -2924,6 +3000,7 @@ Object { }, }, "duration": 0, + "effectDuration": null, "fiberActualDurations": Map { 5 => 0, 4 => 0, @@ -2943,6 +3020,7 @@ Object { 1 => 0, }, "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Immediate", "timestamp": 0, } @@ -2990,6 +3068,7 @@ Object { }, }, "duration": 0, + "effectDuration": null, "fiberActualDurations": Map { 5 => 0, 4 => 0, @@ -3009,6 +3088,7 @@ Object { 1 => 0, }, "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Immediate", "timestamp": 0, } @@ -3073,6 +3153,7 @@ Object { ], ], "duration": 0, + "effectDuration": null, "fiberActualDurations": Array [ Array [ 1, @@ -3134,6 +3215,7 @@ Object { ], ], "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Normal", "timestamp": 0, }, @@ -3199,6 +3281,7 @@ Object { ], ], "duration": 0, + "effectDuration": null, "fiberActualDurations": Array [ Array [ 5, @@ -3252,6 +3335,7 @@ Object { ], ], "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Immediate", "timestamp": 0, }, @@ -3311,6 +3395,7 @@ Object { ], ], "duration": 0, + "effectDuration": null, "fiberActualDurations": Array [ Array [ 5, @@ -3372,6 +3457,7 @@ Object { ], ], "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Immediate", "timestamp": 0, }, @@ -3432,6 +3518,7 @@ Object { ], ], "duration": 0, + "effectDuration": null, "fiberActualDurations": Array [ Array [ 5, @@ -3493,6 +3580,7 @@ Object { ], ], "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Immediate", "timestamp": 0, }, @@ -3552,6 +3640,7 @@ Object { ], ], "duration": 0, + "effectDuration": null, "fiberActualDurations": Array [ Array [ 5, @@ -3613,6 +3702,7 @@ Object { ], ], "interactionIDs": Array [], + "passiveEffectDuration": null, "priorityLevel": "Immediate", "timestamp": 0, }, @@ -3887,6 +3977,7 @@ Object { ], ], "duration": 11, + "effectDuration": null, "fiberActualDurations": Array [ Array [ 1, @@ -3926,6 +4017,7 @@ Object { "interactionIDs": Array [ 0, ], + "passiveEffectDuration": null, "priorityLevel": "Normal", "timestamp": 11, }, @@ -3965,6 +4057,7 @@ Object { ], ], "duration": 11, + "effectDuration": null, "fiberActualDurations": Array [ Array [ 3, @@ -4004,6 +4097,7 @@ Object { "interactionIDs": Array [ 1, ], + "passiveEffectDuration": null, "priorityLevel": "Immediate", "timestamp": 22, }, diff --git a/packages/react-devtools-shared/src/backend/renderer.js b/packages/react-devtools-shared/src/backend/renderer.js index b23b59f73d84a..c2de357a1b5f6 100644 --- a/packages/react-devtools-shared/src/backend/renderer.js +++ b/packages/react-devtools-shared/src/backend/renderer.js @@ -2097,6 +2097,25 @@ export function attach( // Checking root.memoizedInteractions handles multi-renderer edge-case- // where some v16 renderers support profiling and others don't. if (isProfiling && root.memoizedInteractions != null) { + // Profiling durations are only available for certain builds. + // If available, they'll be stored on the HostRoot. + let effectDuration = null; + let passiveEffectDuration = null; + const hostRoot = root.current; + if (hostRoot != null) { + const stateNode = hostRoot.stateNode; + if (stateNode != null) { + effectDuration = + stateNode.effectDuration != null + ? stateNode.effectDuration + : null; + passiveEffectDuration = + stateNode.passiveEffectDuration != null + ? stateNode.passiveEffectDuration + : null; + } + } + // If profiling is active, store commit time and duration, and the current interactions. // The frontend may request this information after profiling has stopped. currentCommitProfilingMetadata = { @@ -2111,6 +2130,8 @@ export function attach( ), maxActualDuration: 0, priorityLevel: null, + effectDuration, + passiveEffectDuration, }; } @@ -2149,6 +2170,23 @@ export function attach( const isProfilingSupported = root.memoizedInteractions != null; if (isProfiling && isProfilingSupported) { + // Profiling durations are only available for certain builds. + // If available, they'll be stored on the HostRoot. + let effectDuration = null; + let passiveEffectDuration = null; + const hostRoot = root.current; + if (hostRoot != null) { + const stateNode = hostRoot.stateNode; + if (stateNode != null) { + effectDuration = + stateNode.effectDuration != null ? stateNode.effectDuration : null; + passiveEffectDuration = + stateNode.passiveEffectDuration != null + ? stateNode.passiveEffectDuration + : null; + } + } + // If profiling is active, store commit time and duration, and the current interactions. // The frontend may request this information after profiling has stopped. currentCommitProfilingMetadata = { @@ -2164,6 +2202,8 @@ export function attach( maxActualDuration: 0, priorityLevel: priorityLevel == null ? null : formatPriorityLevel(priorityLevel), + effectDuration, + passiveEffectDuration, }; } @@ -3294,8 +3334,10 @@ export function attach( changeDescriptions: Map | null, commitTime: number, durations: Array, + effectDuration: number | null, interactions: Array, maxActualDuration: number, + passiveEffectDuration: number | null, priorityLevel: string | null, |}; @@ -3349,8 +3391,10 @@ export function attach( const { changeDescriptions, durations, + effectDuration, interactions, maxActualDuration, + passiveEffectDuration, priorityLevel, commitTime, } = commitProfilingData; @@ -3386,9 +3430,11 @@ export function attach( ? Array.from(changeDescriptions.entries()) : null, duration: maxActualDuration, + effectDuration, fiberActualDurations, fiberSelfDurations, interactionIDs, + passiveEffectDuration, priorityLevel, timestamp: commitTime, }); diff --git a/packages/react-devtools-shared/src/backend/types.js b/packages/react-devtools-shared/src/backend/types.js index 3c42d2f9cc288..627e9a45045ab 100644 --- a/packages/react-devtools-shared/src/backend/types.js +++ b/packages/react-devtools-shared/src/backend/types.js @@ -156,11 +156,15 @@ export type CommitDataBackend = {| // Tuple of fiber ID and change description changeDescriptions: Array<[number, ChangeDescription]> | null, duration: number, + // Only available in certain (newer) React builds, + effectDuration: number | null, // Tuple of fiber ID and actual duration fiberActualDurations: Array<[number, number]>, // Tuple of fiber ID and computed "self" duration fiberSelfDurations: Array<[number, number]>, interactionIDs: Array, + // Only available in certain (newer) React builds, + passiveEffectDuration: number | null, priorityLevel: string | null, timestamp: number, |}; diff --git a/packages/react-devtools-shared/src/devtools/views/Profiler/SidebarCommitInfo.css b/packages/react-devtools-shared/src/devtools/views/Profiler/SidebarCommitInfo.css index c0564e0d8c520..34917846eb329 100644 --- a/packages/react-devtools-shared/src/devtools/views/Profiler/SidebarCommitInfo.css +++ b/packages/react-devtools-shared/src/devtools/views/Profiler/SidebarCommitInfo.css @@ -63,3 +63,19 @@ height: 100%; color: var(--color-dim); } + +.DurationsList { + list-style: none; + margin: 0.25rem 0 0 0; + padding: 0; + background: var(--color-background-inactive); + padding: 0.25rem 0.5rem; + border-radius: 0.25rem; +} + +.DurationsListItem { + margin: 0.25rem 0 0 0; +} +.DurationsListItem:first-of-type { + margin: 0; +} diff --git a/packages/react-devtools-shared/src/devtools/views/Profiler/SidebarCommitInfo.js b/packages/react-devtools-shared/src/devtools/views/Profiler/SidebarCommitInfo.js index 6cff0e209fa9a..ed913984cc7a0 100644 --- a/packages/react-devtools-shared/src/devtools/views/Profiler/SidebarCommitInfo.js +++ b/packages/react-devtools-shared/src/devtools/views/Profiler/SidebarCommitInfo.js @@ -34,7 +34,9 @@ export default function SidebarCommitInfo(_: Props) { const {interactions} = profilerStore.getDataForRoot(rootID); const { duration, + effectDuration, interactionIDs, + passiveEffectDuration, priorityLevel, timestamp, } = profilerStore.getCommitData(rootID, selectedCommitIndex); @@ -44,6 +46,9 @@ export default function SidebarCommitInfo(_: Props) { selectInteraction(interactionID); }; + const hasCommitPhaseDurations = + effectDuration !== null || passiveEffectDuration !== null; + return (
Commit information
@@ -59,10 +64,44 @@ export default function SidebarCommitInfo(_: Props) { :{' '} {formatTime(timestamp)}s -
  • - :{' '} - {formatDuration(duration)}ms -
  • + + {!hasCommitPhaseDurations && ( +
  • + :{' '} + {formatDuration(duration)}ms +
  • + )} + + {hasCommitPhaseDurations && ( +
  • + +
      +
    • + :{' '} + + {formatDuration(duration)}ms + +
    • + {effectDuration !== null && ( +
    • + :{' '} + + {formatDuration(effectDuration)}ms + +
    • + )} + {passiveEffectDuration !== null && ( +
    • + :{' '} + + {formatDuration(passiveEffectDuration)}ms + +
    • + )} +
    +
  • + )} +
  • :
    diff --git a/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotCommitList.css b/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotCommitList.css index 53faae5c38129..ddcb7d9e08c5c 100644 --- a/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotCommitList.css +++ b/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotCommitList.css @@ -7,3 +7,56 @@ */ overflow-x: hidden !important; } + +.Tooltip { + margin-top: 2.5rem; +} + +.TooltipList { + list-style: none; + padding: 0; + margin: 0; +} + +.TooltipListItem { + display: flex; +} + +.TooltipLabel { + font-weight: bold; + margin-right: 0.25rem; +} +.TooltipLabel:after { + content: ':'; +} + +.TooltipValue { + flex-grow: 1; + text-align: end; +} + +.DurationsWrapper { + flex-grow: 1; +} + +.DurationsList { + list-style: none; + margin: 0 0 0 1rem; + padding: 0; +} + +.DurationsListItem { + display: flex; +} + +.DurationsLabel { + margin-right: 0.25rem; +} +.DurationsLabel:after { + content: ':'; +} + +.DurationsValue { + flex-grow: 1; + text-align: end; +} \ No newline at end of file diff --git a/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotCommitList.js b/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotCommitList.js index b4b42ddc82215..4fda4177706ad 100644 --- a/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotCommitList.js +++ b/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotCommitList.js @@ -7,6 +7,8 @@ * @flow */ +import type {CommitDataFrontend} from './types'; + import * as React from 'react'; import {useEffect, useMemo, useRef, useState} from 'react'; import AutoSizer from 'react-virtualized-auto-sizer'; @@ -19,7 +21,6 @@ import Tooltip from './Tooltip'; import styles from './SnapshotCommitList.css'; export type ItemData = {| - commitDurations: Array, commitTimes: Array, filteredCommitIndices: Array, maxDuration: number, @@ -28,36 +29,40 @@ export type ItemData = {| selectCommitIndex: (index: number) => void, setHoveredCommitIndex: (index: number) => void, startCommitDrag: (newDragState: DragState) => void, + totalDurations: Array, |}; type Props = {| - commitDurations: Array, + commitData: CommitDataFrontend, commitTimes: Array, filteredCommitIndices: Array, selectedCommitIndex: number | null, selectedFilteredCommitIndex: number | null, selectCommitIndex: (index: number) => void, + totalDurations: Array, |}; export default function SnapshotCommitList({ - commitDurations, + commitData, commitTimes, filteredCommitIndices, selectedCommitIndex, selectedFilteredCommitIndex, selectCommitIndex, + totalDurations, }: Props) { return ( {({height, width}) => ( )} @@ -66,13 +71,14 @@ export default function SnapshotCommitList({ } type ListProps = {| - commitDurations: Array, + commitData: CommitDataFrontend, commitTimes: Array, height: number, filteredCommitIndices: Array, selectedCommitIndex: number | null, selectedFilteredCommitIndex: number | null, selectCommitIndex: (index: number) => void, + totalDurations: Array, width: number, |}; @@ -83,13 +89,14 @@ type DragState = { }; function List({ - commitDurations, + commitData, selectedCommitIndex, commitTimes, height, filteredCommitIndices, selectedFilteredCommitIndex, selectCommitIndex, + totalDurations, width, }: ListProps) { const listRef = useRef | null>(null); @@ -111,8 +118,8 @@ function List({ [filteredCommitIndices, width], ); const maxDuration = useMemo( - () => commitDurations.reduce((max, duration) => Math.max(max, duration), 0), - [commitDurations], + () => totalDurations.reduce((max, duration) => Math.max(max, duration), 0), + [totalDurations], ); const maxCommitIndex = filteredCommitIndices.length - 1; @@ -176,7 +183,6 @@ function List({ // Pass required contextual data down to the ListItem renderer. const itemData = useMemo( () => ({ - commitDurations, commitTimes, filteredCommitIndices, maxDuration, @@ -185,9 +191,9 @@ function List({ selectCommitIndex, setHoveredCommitIndex, startCommitDrag: setDragState, + totalDurations, }), [ - commitDurations, commitTimes, filteredCommitIndices, maxDuration, @@ -195,20 +201,81 @@ function List({ selectedFilteredCommitIndex, selectCommitIndex, setHoveredCommitIndex, + totalDurations, ], ); let tooltipLabel = null; if (hoveredCommitIndex !== null) { - const commitDuration = commitDurations[hoveredCommitIndex]; - const commitTime = commitTimes[hoveredCommitIndex]; - tooltipLabel = `${formatDuration(commitDuration)}ms at ${formatTime( - commitTime, - )}s`; + const { + duration, + effectDuration, + passiveEffectDuration, + priorityLevel, + timestamp, + } = commitData[hoveredCommitIndex]; + + // Only some React versions include commit durations. + // Show a richer tooltip only for builds that have that info. + if (effectDuration !== null || passiveEffectDuration !== null) { + tooltipLabel = ( +
      + {priorityLevel !== null && ( +
    • + + {priorityLevel} +
    • + )} +
    • + + + {formatTime(timestamp)}s + +
    • +
    • +
      + +
        +
      • + + + {formatDuration(duration)}ms + +
      • + {effectDuration !== null && ( +
      • + + + {formatDuration(effectDuration)}ms + +
      • + )} + {passiveEffectDuration !== null && ( +
      • + + + {formatDuration(passiveEffectDuration)}ms + +
      • + )} +
      +
      +
    • +
    + ); + } else { + tooltipLabel = `${formatDuration(duration)}ms at ${formatTime( + timestamp, + )}s`; + } } return ( - +
    0) { + backgroundColor = getGradientColor(colorScale); + } + return (
    + }}>
    0 ? getGradientColor(colorScale) : undefined, + backgroundColor, }} />
    diff --git a/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotSelector.js b/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotSelector.js index c67b895edf46e..b79569df1e48f 100644 --- a/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotSelector.js +++ b/packages/react-devtools-shared/src/devtools/views/Profiler/SnapshotSelector.js @@ -32,10 +32,14 @@ export default function SnapshotSelector(_: Props) { const {profilerStore} = useContext(StoreContext); const {commitData} = profilerStore.getDataForRoot(((rootID: any): number)); - const commitDurations: Array = []; + const totalDurations: Array = []; const commitTimes: Array = []; commitData.forEach(commitDatum => { - commitDurations.push(commitDatum.duration); + totalDurations.push( + commitDatum.duration + + (commitDatum.effectDuration || 0) + + (commitDatum.passiveEffectDuration || 0), + ); commitTimes.push(commitDatum.timestamp); }); @@ -151,12 +155,13 @@ export default function SnapshotSelector(_: Props) { tabIndex={0}> {numFilteredCommits > 0 && ( )} {numFilteredCommits === 0 && ( diff --git a/packages/react-devtools-shared/src/devtools/views/Profiler/Tooltip.js b/packages/react-devtools-shared/src/devtools/views/Profiler/Tooltip.js index 93955ab0d215f..8e759485a64a1 100644 --- a/packages/react-devtools-shared/src/devtools/views/Profiler/Tooltip.js +++ b/packages/react-devtools-shared/src/devtools/views/Profiler/Tooltip.js @@ -7,7 +7,7 @@ import styles from './Tooltip.css'; const initialTooltipState = {height: 0, mouseX: 0, mouseY: 0, width: 0}; -export default function Tooltip({children, label}: any) { +export default function Tooltip({children, className, label, style}: any) { const containerRef = useRef(null); const tooltipRef = useRef(null); @@ -36,7 +36,10 @@ export default function Tooltip({children, label}: any) { className={styles.Container} onMouseMove={onMouseMove} ref={containerRef}> -
    +
    {label}
    {children} diff --git a/packages/react-devtools-shared/src/devtools/views/Profiler/types.js b/packages/react-devtools-shared/src/devtools/views/Profiler/types.js index 2ca28cefd3cf9..803aeac6a0f0f 100644 --- a/packages/react-devtools-shared/src/devtools/views/Profiler/types.js +++ b/packages/react-devtools-shared/src/devtools/views/Profiler/types.js @@ -52,9 +52,13 @@ export type CommitDataFrontend = {| // Map of Fiber (ID) to a description of what changed in this commit. changeDescriptions: Map | null, - // How long was this commit? + // How long was the render phase? duration: number, + // How long was the layout commit phase? + // Note that not all builds of React expose this property. + effectDuration: number | null, + // Map of Fiber (ID) to actual duration for this commit; // Fibers that did not render will not have entries in this Map. fiberActualDurations: Map, @@ -66,6 +70,10 @@ export type CommitDataFrontend = {| // Which interactions (IDs) were associated with this commit. interactionIDs: Array, + // How long was the passive commit phase? + // Note that not all builds of React expose this property. + passiveEffectDuration: number | null, + // Priority level of the commit (if React provided this info) priorityLevel: string | null, @@ -113,11 +121,13 @@ export type ProfilingDataFrontend = {| export type CommitDataExport = {| changeDescriptions: Array<[number, ChangeDescription]> | null, duration: number, + effectDuration: number | null, // Tuple of fiber ID and actual duration fiberActualDurations: Array<[number, number]>, // Tuple of fiber ID and computed "self" duration fiberSelfDurations: Array<[number, number]>, interactionIDs: Array, + passiveEffectDuration: number | null, priorityLevel: string | null, timestamp: number, |}; diff --git a/packages/react-devtools-shared/src/devtools/views/Profiler/utils.js b/packages/react-devtools-shared/src/devtools/views/Profiler/utils.js index 9691af89a588d..c667276cfafac 100644 --- a/packages/react-devtools-shared/src/devtools/views/Profiler/utils.js +++ b/packages/react-devtools-shared/src/devtools/views/Profiler/utils.js @@ -75,11 +75,13 @@ export function prepareProfilingDataFrontendFromBackendAndStore( ? new Map(commitDataBackend.changeDescriptions) : null, duration: commitDataBackend.duration, + effectDuration: commitDataBackend.effectDuration, fiberActualDurations: new Map( commitDataBackend.fiberActualDurations, ), fiberSelfDurations: new Map(commitDataBackend.fiberSelfDurations), interactionIDs: commitDataBackend.interactionIDs, + passiveEffectDuration: commitDataBackend.passiveEffectDuration, priorityLevel: commitDataBackend.priorityLevel, timestamp: commitDataBackend.timestamp, }), @@ -129,18 +131,22 @@ export function prepareProfilingDataFrontendFromExport( ({ changeDescriptions, duration, + effectDuration, fiberActualDurations, fiberSelfDurations, interactionIDs, + passiveEffectDuration, priorityLevel, timestamp, }) => ({ changeDescriptions: changeDescriptions != null ? new Map(changeDescriptions) : null, duration, + effectDuration, fiberActualDurations: new Map(fiberActualDurations), fiberSelfDurations: new Map(fiberSelfDurations), interactionIDs, + passiveEffectDuration, priorityLevel, timestamp, }), @@ -180,9 +186,11 @@ export function prepareProfilingDataExport( ({ changeDescriptions, duration, + effectDuration, fiberActualDurations, fiberSelfDurations, interactionIDs, + passiveEffectDuration, priorityLevel, timestamp, }) => ({ @@ -191,9 +199,11 @@ export function prepareProfilingDataExport( ? Array.from(changeDescriptions.entries()) : null, duration, + effectDuration, fiberActualDurations: Array.from(fiberActualDurations.entries()), fiberSelfDurations: Array.from(fiberSelfDurations.entries()), interactionIDs, + passiveEffectDuration, priorityLevel, timestamp, }), diff --git a/packages/react-devtools-shell/src/app/InteractionTracing/index.js b/packages/react-devtools-shell/src/app/InteractionTracing/index.js index fd9bb891e0e67..544b335d0b36a 100644 --- a/packages/react-devtools-shell/src/app/InteractionTracing/index.js +++ b/packages/react-devtools-shell/src/app/InteractionTracing/index.js @@ -8,7 +8,13 @@ */ import * as React from 'react'; -import {Fragment, useCallback, useEffect, useState} from 'react'; +import { + Fragment, + useCallback, + useLayoutEffect, + useEffect, + useState, +} from 'react'; import {unstable_batchedUpdates as batchedUpdates} from 'react-dom'; import { unstable_trace as trace, @@ -68,6 +74,10 @@ export default function InteractionTracing() { } }, [count, shouldCascade]); + useLayoutEffect(() => { + Math.sqrt(100 * 100 * 100 * 100 * 100); + }); + return (

    Interaction Tracing