Skip to content

Commit

Permalink
Added Network measures to the Scheduling Profiler
Browse files Browse the repository at this point in the history
Also slightly refactored the preprocessData data function to split separate sections out into helper functions for readability. (We can do more of this for other mark types in a follow up commit.)
  • Loading branch information
Brian Vaughn committed Aug 17, 2021
1 parent 8279dc8 commit 9309d10
Show file tree
Hide file tree
Showing 10 changed files with 787 additions and 118 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 9309d10

Please sign in to comment.