Show commit priority levels in Profiler UI

This commit is contained in:
Brian Vaughn
2019-05-20 09:39:26 -07:00
parent eb736a4c46
commit 2790e55fec
10 changed files with 134 additions and 12 deletions
+29
View File
@@ -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;
+9 -2
View File
@@ -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,
+7 -1
View File
@@ -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
View File
@@ -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 = {
+4 -1
View File
@@ -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}>
+2
View File
@@ -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>,
|};
+32 -2
View File
@@ -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
View File
@@ -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);
}
}