mirror of
https://github.com/hanzoai/react.git
synced 2026-09-24 17:02:27 +00:00
Show commit priority levels in Profiler UI
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
// @flow
|
||||
|
||||
import React, { Fragment, useCallback, useState } from 'react';
|
||||
import { unstable_next as next } from 'scheduler';
|
||||
|
||||
export default function PriorityLevels() {
|
||||
const [count, setCount] = useState(0);
|
||||
|
||||
const startSequence = useCallback(() => {
|
||||
setCount(1);
|
||||
next(() => setCount(2));
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<h1>Priority Levels</h1>
|
||||
<button onClick={startSequence}>start sequence</button>
|
||||
{count >= 1 && <Text>One</Text>}
|
||||
{count >= 2 && <Text>Two</Text>}
|
||||
{count >= 2 && (
|
||||
<div hidden>
|
||||
<Text>Three</Text>
|
||||
</div>
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
const Text = ({ children }) => children;
|
||||
@@ -3,12 +3,17 @@
|
||||
// This test harness mounts each test app as a separate root to test multi-root applications.
|
||||
|
||||
import { createElement } from 'react';
|
||||
import { render, unmountComponentAtNode } from 'react-dom';
|
||||
import {
|
||||
unmountComponentAtNode,
|
||||
// $FlowFixMe Flow does not yet know about createRoot()
|
||||
unstable_createRoot as createRoot,
|
||||
} from 'react-dom';
|
||||
import DeeplyNestedComponents from './DeeplyNestedComponents';
|
||||
import EditableProps from './EditableProps';
|
||||
import ElementTypes from './ElementTypes';
|
||||
import InspectableElements from './InspectableElements';
|
||||
import InteractionTracing from './InteractionTracing';
|
||||
import PriorityLevels from './PriorityLevels';
|
||||
import ToDoList from './ToDoList';
|
||||
import Toggle from './Toggle';
|
||||
import SuspenseTree from './SuspenseTree';
|
||||
@@ -24,7 +29,8 @@ function mountHelper(App) {
|
||||
|
||||
containers.push(container);
|
||||
|
||||
render(createElement(App), container);
|
||||
const root = createRoot(container);
|
||||
root.render(createElement(App));
|
||||
}
|
||||
|
||||
function mountTestApp() {
|
||||
@@ -33,6 +39,7 @@ function mountTestApp() {
|
||||
mountHelper(InspectableElements);
|
||||
mountHelper(ElementTypes);
|
||||
mountHelper(EditableProps);
|
||||
mountHelper(PriorityLevels);
|
||||
mountHelper(Toggle);
|
||||
mountHelper(SuspenseTree);
|
||||
mountHelper(DeeplyNestedComponents);
|
||||
|
||||
@@ -11,6 +11,7 @@ Object {
|
||||
},
|
||||
"commitIndex": 0,
|
||||
"interactions": Array [],
|
||||
"priorityLevel": 99,
|
||||
"rootID": 1,
|
||||
"selfDurations": Map {
|
||||
1 => 0,
|
||||
@@ -33,6 +34,7 @@ Object {
|
||||
},
|
||||
"commitIndex": 1,
|
||||
"interactions": Array [],
|
||||
"priorityLevel": 99,
|
||||
"rootID": 1,
|
||||
"selfDurations": Map {
|
||||
3 => 0,
|
||||
@@ -53,6 +55,7 @@ Object {
|
||||
},
|
||||
"commitIndex": 2,
|
||||
"interactions": Array [],
|
||||
"priorityLevel": 99,
|
||||
"rootID": 1,
|
||||
"selfDurations": Map {
|
||||
3 => 0,
|
||||
@@ -70,6 +73,7 @@ Object {
|
||||
},
|
||||
"commitIndex": 3,
|
||||
"interactions": Array [],
|
||||
"priorityLevel": 99,
|
||||
"rootID": 1,
|
||||
"selfDurations": Map {
|
||||
2 => 10,
|
||||
@@ -91,6 +95,7 @@ Object {
|
||||
},
|
||||
"commitIndex": 0,
|
||||
"interactions": Array [],
|
||||
"priorityLevel": 99,
|
||||
"rootID": 1,
|
||||
"selfDurations": Map {
|
||||
1 => 0,
|
||||
@@ -110,6 +115,7 @@ Object {
|
||||
},
|
||||
"commitIndex": 1,
|
||||
"interactions": Array [],
|
||||
"priorityLevel": 99,
|
||||
"rootID": 1,
|
||||
"selfDurations": Map {
|
||||
3 => 0,
|
||||
@@ -127,6 +133,7 @@ Object {
|
||||
},
|
||||
"commitIndex": 2,
|
||||
"interactions": Array [],
|
||||
"priorityLevel": 99,
|
||||
"rootID": 1,
|
||||
"selfDurations": Map {
|
||||
3 => 0,
|
||||
@@ -141,6 +148,7 @@ Object {
|
||||
},
|
||||
"commitIndex": 3,
|
||||
"interactions": Array [],
|
||||
"priorityLevel": 99,
|
||||
"rootID": 1,
|
||||
"selfDurations": Map {
|
||||
2 => 10,
|
||||
@@ -324,6 +332,7 @@ Object {
|
||||
},
|
||||
"commitIndex": 0,
|
||||
"interactions": Array [],
|
||||
"priorityLevel": 99,
|
||||
"rootID": 1,
|
||||
"selfDurations": Map {
|
||||
1 => 0,
|
||||
@@ -344,6 +353,7 @@ Object {
|
||||
},
|
||||
"commitIndex": 0,
|
||||
"interactions": Array [],
|
||||
"priorityLevel": 99,
|
||||
"rootID": 1,
|
||||
"selfDurations": Map {
|
||||
1 => 0,
|
||||
@@ -362,6 +372,7 @@ Object {
|
||||
},
|
||||
"commitIndex": 1,
|
||||
"interactions": Array [],
|
||||
"priorityLevel": 99,
|
||||
"rootID": 1,
|
||||
"selfDurations": Map {
|
||||
5 => 3,
|
||||
@@ -447,6 +458,7 @@ Object {
|
||||
},
|
||||
"commitIndex": 0,
|
||||
"interactions": Array [],
|
||||
"priorityLevel": 99,
|
||||
"rootID": 1,
|
||||
"selfDurations": Map {
|
||||
1 => 0,
|
||||
@@ -464,6 +476,7 @@ Object {
|
||||
},
|
||||
"commitIndex": 1,
|
||||
"interactions": Array [],
|
||||
"priorityLevel": 99,
|
||||
"rootID": 1,
|
||||
"selfDurations": Map {
|
||||
3 => 0,
|
||||
@@ -482,6 +495,7 @@ Object {
|
||||
},
|
||||
"commitIndex": 2,
|
||||
"interactions": Array [],
|
||||
"priorityLevel": 99,
|
||||
"rootID": 1,
|
||||
"selfDurations": Map {
|
||||
3 => 0,
|
||||
@@ -696,6 +710,7 @@ Object {
|
||||
"timestamp": 0,
|
||||
},
|
||||
],
|
||||
"priorityLevel": 99,
|
||||
"rootID": 1,
|
||||
"selfDurations": Map {
|
||||
1 => 0,
|
||||
@@ -720,6 +735,7 @@ Object {
|
||||
"timestamp": 11,
|
||||
},
|
||||
],
|
||||
"priorityLevel": 99,
|
||||
"rootID": 1,
|
||||
"selfDurations": Map {
|
||||
3 => 0,
|
||||
@@ -906,6 +922,7 @@ Object {
|
||||
},
|
||||
"commitIndex": 0,
|
||||
"interactions": Array [],
|
||||
"priorityLevel": 99,
|
||||
"rootID": 1,
|
||||
"selfDurations": Map {
|
||||
3 => 0,
|
||||
@@ -923,6 +940,7 @@ Object {
|
||||
},
|
||||
"commitIndex": 1,
|
||||
"interactions": Array [],
|
||||
"priorityLevel": 99,
|
||||
"rootID": 1,
|
||||
"selfDurations": Map {
|
||||
3 => 0,
|
||||
@@ -937,6 +955,7 @@ Object {
|
||||
},
|
||||
"commitIndex": 2,
|
||||
"interactions": Array [],
|
||||
"priorityLevel": 99,
|
||||
"rootID": 1,
|
||||
"selfDurations": Map {
|
||||
2 => 10,
|
||||
|
||||
@@ -48,6 +48,7 @@ import type {
|
||||
PathFrame,
|
||||
PathMatch,
|
||||
ProfilingSummaryBackend,
|
||||
ReactPriorityLevel,
|
||||
ReactRenderer,
|
||||
RendererInterface,
|
||||
} from './types';
|
||||
@@ -1267,6 +1268,7 @@ export function attach(
|
||||
})
|
||||
),
|
||||
maxActualDuration: 0,
|
||||
priorityLevel: null,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1284,7 +1286,7 @@ export function attach(
|
||||
recordUnmount(fiber, false);
|
||||
}
|
||||
|
||||
function handleCommitFiberRoot(root) {
|
||||
function handleCommitFiberRoot(root, priorityLevel) {
|
||||
const current = root.current;
|
||||
const alternate = current.alternate;
|
||||
|
||||
@@ -1309,6 +1311,7 @@ export function attach(
|
||||
})
|
||||
),
|
||||
maxActualDuration: 0,
|
||||
priorityLevel: priorityLevel || null,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1955,6 +1958,7 @@ export function attach(
|
||||
durations: Array<number>,
|
||||
interactions: Array<InteractionBackend>,
|
||||
maxActualDuration: number,
|
||||
priorityLevel: ReactPriorityLevel | null,
|
||||
|};
|
||||
|
||||
type CommitProfilingMetadataMap = Map<number, Array<CommitProfilingData>>;
|
||||
@@ -1980,6 +1984,7 @@ export function attach(
|
||||
commitIndex,
|
||||
durations: commitProfilingData.durations,
|
||||
interactions: commitProfilingData.interactions,
|
||||
priorityLevel: commitProfilingData.priorityLevel,
|
||||
rootID,
|
||||
};
|
||||
}
|
||||
@@ -1993,6 +1998,7 @@ export function attach(
|
||||
commitIndex,
|
||||
durations: [],
|
||||
interactions: [],
|
||||
priorityLevel: null,
|
||||
rootID,
|
||||
};
|
||||
}
|
||||
|
||||
+20
-2
@@ -32,6 +32,16 @@ export type HookType =
|
||||
| 'useImperativeHandle'
|
||||
| 'useDebugValue';
|
||||
|
||||
// Priority level is copied from React and should be kept in sync:
|
||||
// https://github.com/facebook/react/blob/master/packages/react-reconciler/src/SchedulerWithReactIntegration.js
|
||||
export opaque type ReactPriorityLevel = 99 | 98 | 97 | 96 | 95 | 90;
|
||||
export const ImmediatePriority: ReactPriorityLevel = 99;
|
||||
export const UserBlockingPriority: ReactPriorityLevel = 98;
|
||||
export const NormalPriority: ReactPriorityLevel = 97;
|
||||
export const LowPriority: ReactPriorityLevel = 96;
|
||||
export const IdlePriority: ReactPriorityLevel = 95;
|
||||
export const NoPriority: ReactPriorityLevel = 90;
|
||||
|
||||
// The Fiber type is copied from React and should be kept in sync:
|
||||
// https://github.com/facebook/react/blob/master/packages/react-reconciler/src/ReactFiber.js
|
||||
// The properties we don't use in DevTools are omitted.
|
||||
@@ -126,6 +136,7 @@ export type CommitDetailsBackend = {|
|
||||
// An interleaved array: fiberID at [i], actualDuration at [i + 1], computed selfDuration at [i + 2].
|
||||
durations: Array<number>,
|
||||
interactions: Array<InteractionBackend>,
|
||||
priorityLevel: ReactPriorityLevel | null,
|
||||
rootID: number,
|
||||
|};
|
||||
|
||||
@@ -193,7 +204,10 @@ export type RendererInterface = {
|
||||
) => ExportedProfilingDataFromRenderer,
|
||||
getProfilingSummary: (rootID: number) => ProfilingSummaryBackend,
|
||||
getPathForElement: (id: number) => Array<PathFrame> | null,
|
||||
handleCommitFiberRoot: (fiber: Object) => void,
|
||||
handleCommitFiberRoot: (
|
||||
fiber: Object,
|
||||
commitPriority?: ReactPriorityLevel
|
||||
) => void,
|
||||
handleCommitFiberUnmount: (fiber: Object) => void,
|
||||
inspectElement: (id: number) => InspectedElement | null,
|
||||
logElementToConsole: (id: number) => void,
|
||||
@@ -234,7 +248,11 @@ export type DevToolsHook = {
|
||||
// React uses these methods.
|
||||
checkDCE: (fn: Function) => void,
|
||||
onCommitFiberUnmount: (rendererID: RendererID, fiber: Object) => void,
|
||||
onCommitFiberRoot: (rendererID: RendererID, fiber: Object) => void,
|
||||
onCommitFiberRoot: (
|
||||
rendererID: RendererID,
|
||||
fiber: Object,
|
||||
commitPriority?: ReactPriorityLevel
|
||||
) => void,
|
||||
};
|
||||
|
||||
export type HooksNode = {
|
||||
|
||||
@@ -130,8 +130,9 @@ export default class ProfilingCache {
|
||||
rootID,
|
||||
commitIndex,
|
||||
actualDurations: new Map(),
|
||||
selfDurations: new Map(),
|
||||
priorityLevel: null,
|
||||
interactions: [],
|
||||
selfDurations: new Map(),
|
||||
});
|
||||
});
|
||||
},
|
||||
@@ -346,6 +347,7 @@ export default class ProfilingCache {
|
||||
commitIndex,
|
||||
durations,
|
||||
interactions,
|
||||
priorityLevel,
|
||||
rootID,
|
||||
}: CommitDetailsBackend) => {
|
||||
const key = `${rootID}-${commitIndex}`;
|
||||
@@ -365,6 +367,7 @@ export default class ProfilingCache {
|
||||
actualDurations: actualDurationsMap,
|
||||
commitIndex,
|
||||
interactions,
|
||||
priorityLevel,
|
||||
rootID,
|
||||
selfDurations: selfDurationsMap,
|
||||
});
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import React, { Fragment, useCallback, useContext, useState } from 'react';
|
||||
import { ProfilerContext } from './ProfilerContext';
|
||||
import { formatDuration, formatTime } from './utils';
|
||||
import { formatDuration, formatPriorityLevel, formatTime } from './utils';
|
||||
import { StoreContext } from '../context';
|
||||
|
||||
import styles from './SidebarCommitInfo.css';
|
||||
@@ -56,7 +56,7 @@ export default function SidebarCommitInfo(_: Props) {
|
||||
}
|
||||
);
|
||||
|
||||
const { interactions } = profilingCache.CommitDetails.read({
|
||||
const { interactions, priorityLevel } = profilingCache.CommitDetails.read({
|
||||
commitIndex: selectedCommitIndex,
|
||||
rendererID: ((rendererID: any): number),
|
||||
rootID: ((rootID: any): number),
|
||||
@@ -72,6 +72,14 @@ export default function SidebarCommitInfo(_: Props) {
|
||||
<div className={styles.Toolbar}>Commit information</div>
|
||||
<div className={styles.Content}>
|
||||
<ul className={styles.List}>
|
||||
{priorityLevel !== null && (
|
||||
<li className={styles.ListItem}>
|
||||
<label className={styles.Label}>Priority</label>:{' '}
|
||||
<span className={styles.Value}>
|
||||
{formatPriorityLevel(priorityLevel)}
|
||||
</span>
|
||||
</li>
|
||||
)}
|
||||
<li className={styles.ListItem}>
|
||||
<label className={styles.Label}>Committed at</label>:{' '}
|
||||
<span className={styles.Value}>
|
||||
|
||||
@@ -5,6 +5,7 @@ import type {
|
||||
CommitDetailsBackend,
|
||||
InteractionsBackend,
|
||||
ProfilingSummaryBackend,
|
||||
ReactPriorityLevel,
|
||||
} from 'src/backend/types';
|
||||
|
||||
export type CommitTreeNodeFrontend = {|
|
||||
@@ -42,6 +43,7 @@ export type CommitDetailsFrontend = {|
|
||||
actualDurations: Map<number, number>,
|
||||
commitIndex: number,
|
||||
interactions: Array<InteractionFrontend>,
|
||||
priorityLevel: ReactPriorityLevel | null,
|
||||
rootID: number,
|
||||
selfDurations: Map<number, number>,
|
||||
|};
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
// @flow
|
||||
|
||||
import { PROFILER_EXPORT_VERSION } from 'src/constants';
|
||||
import {
|
||||
ImmediatePriority,
|
||||
UserBlockingPriority,
|
||||
NormalPriority,
|
||||
LowPriority,
|
||||
IdlePriority,
|
||||
NoPriority,
|
||||
} from 'src/backend/types';
|
||||
|
||||
import type {
|
||||
ExportedProfilingSummaryFromFrontend,
|
||||
@@ -9,7 +17,10 @@ import type {
|
||||
ProfilingSnapshotNode,
|
||||
} from './types';
|
||||
|
||||
import type { ExportedProfilingDataFromRenderer } from 'src/backend/types';
|
||||
import type {
|
||||
ExportedProfilingDataFromRenderer,
|
||||
ReactPriorityLevel,
|
||||
} from 'src/backend/types';
|
||||
|
||||
const commitGradient = [
|
||||
'var(--color-commit-gradient-0)',
|
||||
@@ -152,10 +163,11 @@ export const prepareImportedProfilingData = (
|
||||
}
|
||||
return {
|
||||
actualDurations: actualDurationsMap,
|
||||
selfDurations: selfDurationsMap,
|
||||
commitIndex: commitDetailsBackendItem.commitIndex,
|
||||
interactions: commitDetailsBackendItem.interactions,
|
||||
priorityLevel: commitDetailsBackendItem.priorityLevel,
|
||||
rootID: commitDetailsBackendItem.rootID,
|
||||
selfDurations: selfDurationsMap,
|
||||
};
|
||||
}
|
||||
),
|
||||
@@ -184,6 +196,24 @@ export const getGradientColor = (value: number) => {
|
||||
return commitGradient[Math.round(index)];
|
||||
};
|
||||
|
||||
export const formatPriorityLevel = (priorityLevel: ReactPriorityLevel) => {
|
||||
switch (priorityLevel) {
|
||||
case ImmediatePriority:
|
||||
return 'Immediate';
|
||||
case UserBlockingPriority:
|
||||
return 'User-Blocking';
|
||||
case NormalPriority:
|
||||
return 'Normal';
|
||||
case LowPriority:
|
||||
return 'Low';
|
||||
case IdlePriority:
|
||||
return 'Idle';
|
||||
case NoPriority:
|
||||
default:
|
||||
return 'Unknown';
|
||||
}
|
||||
};
|
||||
|
||||
export const formatDuration = (duration: number) =>
|
||||
Math.round(duration * 10) / 10 || '<0.1';
|
||||
export const formatPercentage = (percentage: number) =>
|
||||
|
||||
+2
-2
@@ -138,7 +138,7 @@ export function installHook(target: any): DevToolsHook | null {
|
||||
}
|
||||
}
|
||||
|
||||
function onCommitFiberRoot(rendererID, root) {
|
||||
function onCommitFiberRoot(rendererID, root, priorityLevel) {
|
||||
const mountedRoots = hook.getFiberRoots(rendererID);
|
||||
const current = root.current;
|
||||
const isKnownRoot = mountedRoots.has(root);
|
||||
@@ -153,7 +153,7 @@ export function installHook(target: any): DevToolsHook | null {
|
||||
}
|
||||
const rendererInterface = rendererInterfaces.get(rendererID);
|
||||
if (rendererInterface != null) {
|
||||
rendererInterface.handleCommitFiberRoot(root);
|
||||
rendererInterface.handleCommitFiberRoot(root, priorityLevel);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user