Skip to content

Commit

Permalink
Scheduling Profiler: Add network measures (#22112)
Browse files Browse the repository at this point in the history
  • Loading branch information
Brian Vaughn authored Aug 18, 2021
1 parent 9eb2aaa commit f51579f
Show file tree
Hide file tree
Showing 14 changed files with 872 additions and 136 deletions.
106 changes: 90 additions & 16 deletions packages/react-devtools-scheduling-profiler/src/CanvasPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import {
ComponentMeasuresView,
FlamechartView,
NativeEventsView,
NetworkMeasuresView,
ReactMeasuresView,
SchedulingEventsView,
SnapshotsView,
Expand Down Expand Up @@ -128,6 +129,18 @@ const zoomToBatch = (
viewState.updateHorizontalScrollState(scrollState);
};

const EMPTY_CONTEXT_INFO: ReactHoverContextInfo = {
componentMeasure: null,
flamechartStackFrame: null,
measure: null,
nativeEvent: null,
networkMeasure: null,
schedulingEvent: null,
snapshot: null,
suspenseEvent: null,
userTimingMark: null,
};

type AutoSizedCanvasProps = {|
data: ReactProfilerData,
height: number,
Expand All @@ -150,14 +163,20 @@ function AutoSizedCanvas({
setHoveredEvent,
] = useState<ReactHoverContextInfo | null>(null);

const surfaceRef = useRef(new Surface());
const resetHoveredEvent = useCallback(
() => setHoveredEvent(EMPTY_CONTEXT_INFO),
[],
);

const surfaceRef = useRef(new Surface(resetHoveredEvent));
const userTimingMarksViewRef = useRef(null);
const nativeEventsViewRef = useRef(null);
const schedulingEventsViewRef = useRef(null);
const suspenseEventsViewRef = useRef(null);
const componentMeasuresViewRef = useRef(null);
const reactMeasuresViewRef = useRef(null);
const flamechartViewRef = useRef(null);
const networkMeasuresViewRef = useRef(null);
const snapshotsViewRef = useRef(null);

const {hideMenu: hideContextMenu} = useContext(RegistryContext);
Expand Down Expand Up @@ -318,6 +337,22 @@ function AutoSizedCanvas({
);
}

let networkMeasuresViewWrapper = null;
if (data.snapshots.length > 0) {
const networkMeasuresView = new NetworkMeasuresView(
surface,
defaultFrame,
data,
);
networkMeasuresViewRef.current = networkMeasuresView;
networkMeasuresViewWrapper = createViewHelper(
networkMeasuresView,
'network',
true,
true,
);
}

const flamechartView = new FlamechartView(
surface,
defaultFrame,
Expand Down Expand Up @@ -357,6 +392,9 @@ function AutoSizedCanvas({
if (snapshotsViewWrapper !== null) {
rootView.addSubview(snapshotsViewWrapper);
}
if (networkMeasuresViewWrapper !== null) {
rootView.addSubview(networkMeasuresViewWrapper);
}
rootView.addSubview(flamechartViewWrapper);

const verticalScrollOverflowView = new VerticalScrollOverflowView(
Expand Down Expand Up @@ -395,16 +433,18 @@ function AutoSizedCanvas({
prevHoverEvent.flamechartStackFrame !== null ||
prevHoverEvent.measure !== null ||
prevHoverEvent.nativeEvent !== null ||
prevHoverEvent.networkMeasure !== null ||
prevHoverEvent.schedulingEvent !== null ||
prevHoverEvent.snapshot !== null ||
prevHoverEvent.suspenseEvent !== null ||
prevHoverEvent.userTimingMark !== null
) {
return {
componentMeasure: null,
data: prevHoverEvent.data,
flamechartStackFrame: null,
measure: null,
nativeEvent: null,
networkMeasure: null,
schedulingEvent: null,
snapshot: null,
suspenseEvent: null,
Expand Down Expand Up @@ -460,10 +500,10 @@ function AutoSizedCanvas({
if (!hoveredEvent || hoveredEvent.userTimingMark !== userTimingMark) {
setHoveredEvent({
componentMeasure: null,
data,
flamechartStackFrame: null,
measure: null,
nativeEvent: null,
networkMeasure: null,
schedulingEvent: null,
snapshot: null,
suspenseEvent: null,
Expand All @@ -479,10 +519,10 @@ function AutoSizedCanvas({
if (!hoveredEvent || hoveredEvent.nativeEvent !== nativeEvent) {
setHoveredEvent({
componentMeasure: null,
data,
flamechartStackFrame: null,
measure: null,
nativeEvent,
networkMeasure: null,
schedulingEvent: null,
snapshot: null,
suspenseEvent: null,
Expand All @@ -498,10 +538,10 @@ function AutoSizedCanvas({
if (!hoveredEvent || hoveredEvent.schedulingEvent !== schedulingEvent) {
setHoveredEvent({
componentMeasure: null,
data,
flamechartStackFrame: null,
measure: null,
nativeEvent: null,
networkMeasure: null,
schedulingEvent,
snapshot: null,
suspenseEvent: null,
Expand All @@ -517,10 +557,10 @@ function AutoSizedCanvas({
if (!hoveredEvent || hoveredEvent.suspenseEvent !== suspenseEvent) {
setHoveredEvent({
componentMeasure: null,
data,
flamechartStackFrame: null,
measure: null,
nativeEvent: null,
networkMeasure: null,
schedulingEvent: null,
snapshot: null,
suspenseEvent,
Expand All @@ -536,10 +576,10 @@ function AutoSizedCanvas({
if (!hoveredEvent || hoveredEvent.measure !== measure) {
setHoveredEvent({
componentMeasure: null,
data,
flamechartStackFrame: null,
measure,
nativeEvent: null,
networkMeasure: null,
schedulingEvent: null,
snapshot: null,
suspenseEvent: null,
Expand All @@ -558,10 +598,10 @@ function AutoSizedCanvas({
) {
setHoveredEvent({
componentMeasure,
data,
flamechartStackFrame: null,
measure: null,
nativeEvent: null,
networkMeasure: null,
schedulingEvent: null,
snapshot: null,
suspenseEvent: null,
Expand All @@ -577,10 +617,10 @@ function AutoSizedCanvas({
if (!hoveredEvent || hoveredEvent.snapshot !== snapshot) {
setHoveredEvent({
componentMeasure: null,
data,
flamechartStackFrame: null,
measure: null,
nativeEvent: null,
networkMeasure: null,
schedulingEvent: null,
snapshot,
suspenseEvent: null,
Expand All @@ -599,10 +639,10 @@ function AutoSizedCanvas({
) {
setHoveredEvent({
componentMeasure: null,
data,
flamechartStackFrame,
measure: null,
nativeEvent: null,
networkMeasure: null,
schedulingEvent: null,
snapshot: null,
suspenseEvent: null,
Expand All @@ -611,53 +651,79 @@ function AutoSizedCanvas({
}
});
}

const {current: networkMeasuresView} = networkMeasuresViewRef;
if (networkMeasuresView) {
networkMeasuresView.onHover = networkMeasure => {
if (!hoveredEvent || hoveredEvent.networkMeasure !== networkMeasure) {
setHoveredEvent({
componentMeasure: null,
flamechartStackFrame: null,
measure: null,
nativeEvent: null,
networkMeasure,
schedulingEvent: null,
snapshot: null,
suspenseEvent: null,
userTimingMark: null,
});
}
};
}
}, [
hoveredEvent,
data, // Attach onHover callbacks when views are re-created on data change
]);

useLayoutEffect(() => {
const {current: userTimingMarksView} = userTimingMarksViewRef;
const userTimingMarksView = userTimingMarksViewRef.current;
if (userTimingMarksView) {
userTimingMarksView.setHoveredMark(
hoveredEvent ? hoveredEvent.userTimingMark : null,
);
}

const {current: nativeEventsView} = nativeEventsViewRef;
const nativeEventsView = nativeEventsViewRef.current;
if (nativeEventsView) {
nativeEventsView.setHoveredEvent(
hoveredEvent ? hoveredEvent.nativeEvent : null,
);
}

const {current: schedulingEventsView} = schedulingEventsViewRef;
const schedulingEventsView = schedulingEventsViewRef.current;
if (schedulingEventsView) {
schedulingEventsView.setHoveredEvent(
hoveredEvent ? hoveredEvent.schedulingEvent : null,
);
}

const {current: suspenseEventsView} = suspenseEventsViewRef;
const suspenseEventsView = suspenseEventsViewRef.current;
if (suspenseEventsView) {
suspenseEventsView.setHoveredEvent(
hoveredEvent ? hoveredEvent.suspenseEvent : null,
);
}

const {current: reactMeasuresView} = reactMeasuresViewRef;
const reactMeasuresView = reactMeasuresViewRef.current;
if (reactMeasuresView) {
reactMeasuresView.setHoveredMeasure(
hoveredEvent ? hoveredEvent.measure : null,
);
}

const {current: flamechartView} = flamechartViewRef;
const flamechartView = flamechartViewRef.current;
if (flamechartView) {
flamechartView.setHoveredFlamechartStackFrame(
hoveredEvent ? hoveredEvent.flamechartStackFrame : null,
);
}

const networkMeasuresView = networkMeasuresViewRef.current;
if (networkMeasuresView) {
networkMeasuresView.setHoveredEvent(
hoveredEvent ? hoveredEvent.networkMeasure : null,
);
}
}, [hoveredEvent]);

// Draw to canvas in React's commit phase
Expand All @@ -677,6 +743,7 @@ function AutoSizedCanvas({
componentMeasure,
flamechartStackFrame,
measure,
networkMeasure,
schedulingEvent,
suspenseEvent,
} = contextData.hoveredEvent;
Expand All @@ -689,6 +756,13 @@ function AutoSizedCanvas({
Copy component name
</ContextMenuItem>
)}
{networkMeasure !== null && (
<ContextMenuItem
onClick={() => copy(networkMeasure.url)}
title="Copy URL">
Copy URL
</ContextMenuItem>
)}
{schedulingEvent !== null && (
<ContextMenuItem
onClick={() => copy(schedulingEvent.componentName)}
Expand Down
15 changes: 13 additions & 2 deletions packages/react-devtools-scheduling-profiler/src/EventTooltip.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
}

.TooltipSection,
.TooltipWarningSection {
.TooltipWarningSection,
.SingleLineTextSection {
display: block;
border-radius: 0.125rem;
max-width: 300px;
padding: 0.25rem;
user-select: none;
pointer-events: none;
Expand All @@ -19,6 +19,13 @@
margin-top: 0.25rem;
background-color: var(--color-warning-background);
}
.TooltipSection,
.TooltipWarningSection {
max-width: 300px;
}
.SingleLineTextSection {
white-space: nowrap;
}

.Divider {
height: 1px;
Expand Down Expand Up @@ -75,4 +82,8 @@

.Image {
border: 1px solid var(--color-border);
}

.DimText {
color: var(--color-dim);
}
Loading

0 comments on commit f51579f

Please sign in to comment.