Skip to content

Commit 6dcbee1

Browse files
Brian Vaughnzhengjitf
Brian Vaughn
authored andcommitted
Scheduling Profiler: Add network measures (facebook#22112)
1 parent c86c894 commit 6dcbee1

File tree

14 files changed

+872
-136
lines changed

14 files changed

+872
-136
lines changed

packages/react-devtools-scheduling-profiler/src/CanvasPage.js

+90-16
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import {
4444
ComponentMeasuresView,
4545
FlamechartView,
4646
NativeEventsView,
47+
NetworkMeasuresView,
4748
ReactMeasuresView,
4849
SchedulingEventsView,
4950
SnapshotsView,
@@ -128,6 +129,18 @@ const zoomToBatch = (
128129
viewState.updateHorizontalScrollState(scrollState);
129130
};
130131

132+
const EMPTY_CONTEXT_INFO: ReactHoverContextInfo = {
133+
componentMeasure: null,
134+
flamechartStackFrame: null,
135+
measure: null,
136+
nativeEvent: null,
137+
networkMeasure: null,
138+
schedulingEvent: null,
139+
snapshot: null,
140+
suspenseEvent: null,
141+
userTimingMark: null,
142+
};
143+
131144
type AutoSizedCanvasProps = {|
132145
data: ReactProfilerData,
133146
height: number,
@@ -150,14 +163,20 @@ function AutoSizedCanvas({
150163
setHoveredEvent,
151164
] = useState<ReactHoverContextInfo | null>(null);
152165

153-
const surfaceRef = useRef(new Surface());
166+
const resetHoveredEvent = useCallback(
167+
() => setHoveredEvent(EMPTY_CONTEXT_INFO),
168+
[],
169+
);
170+
171+
const surfaceRef = useRef(new Surface(resetHoveredEvent));
154172
const userTimingMarksViewRef = useRef(null);
155173
const nativeEventsViewRef = useRef(null);
156174
const schedulingEventsViewRef = useRef(null);
157175
const suspenseEventsViewRef = useRef(null);
158176
const componentMeasuresViewRef = useRef(null);
159177
const reactMeasuresViewRef = useRef(null);
160178
const flamechartViewRef = useRef(null);
179+
const networkMeasuresViewRef = useRef(null);
161180
const snapshotsViewRef = useRef(null);
162181

163182
const {hideMenu: hideContextMenu} = useContext(RegistryContext);
@@ -318,6 +337,22 @@ function AutoSizedCanvas({
318337
);
319338
}
320339

340+
let networkMeasuresViewWrapper = null;
341+
if (data.snapshots.length > 0) {
342+
const networkMeasuresView = new NetworkMeasuresView(
343+
surface,
344+
defaultFrame,
345+
data,
346+
);
347+
networkMeasuresViewRef.current = networkMeasuresView;
348+
networkMeasuresViewWrapper = createViewHelper(
349+
networkMeasuresView,
350+
'network',
351+
true,
352+
true,
353+
);
354+
}
355+
321356
const flamechartView = new FlamechartView(
322357
surface,
323358
defaultFrame,
@@ -357,6 +392,9 @@ function AutoSizedCanvas({
357392
if (snapshotsViewWrapper !== null) {
358393
rootView.addSubview(snapshotsViewWrapper);
359394
}
395+
if (networkMeasuresViewWrapper !== null) {
396+
rootView.addSubview(networkMeasuresViewWrapper);
397+
}
360398
rootView.addSubview(flamechartViewWrapper);
361399

362400
const verticalScrollOverflowView = new VerticalScrollOverflowView(
@@ -395,16 +433,18 @@ function AutoSizedCanvas({
395433
prevHoverEvent.flamechartStackFrame !== null ||
396434
prevHoverEvent.measure !== null ||
397435
prevHoverEvent.nativeEvent !== null ||
436+
prevHoverEvent.networkMeasure !== null ||
398437
prevHoverEvent.schedulingEvent !== null ||
438+
prevHoverEvent.snapshot !== null ||
399439
prevHoverEvent.suspenseEvent !== null ||
400440
prevHoverEvent.userTimingMark !== null
401441
) {
402442
return {
403443
componentMeasure: null,
404-
data: prevHoverEvent.data,
405444
flamechartStackFrame: null,
406445
measure: null,
407446
nativeEvent: null,
447+
networkMeasure: null,
408448
schedulingEvent: null,
409449
snapshot: null,
410450
suspenseEvent: null,
@@ -460,10 +500,10 @@ function AutoSizedCanvas({
460500
if (!hoveredEvent || hoveredEvent.userTimingMark !== userTimingMark) {
461501
setHoveredEvent({
462502
componentMeasure: null,
463-
data,
464503
flamechartStackFrame: null,
465504
measure: null,
466505
nativeEvent: null,
506+
networkMeasure: null,
467507
schedulingEvent: null,
468508
snapshot: null,
469509
suspenseEvent: null,
@@ -479,10 +519,10 @@ function AutoSizedCanvas({
479519
if (!hoveredEvent || hoveredEvent.nativeEvent !== nativeEvent) {
480520
setHoveredEvent({
481521
componentMeasure: null,
482-
data,
483522
flamechartStackFrame: null,
484523
measure: null,
485524
nativeEvent,
525+
networkMeasure: null,
486526
schedulingEvent: null,
487527
snapshot: null,
488528
suspenseEvent: null,
@@ -498,10 +538,10 @@ function AutoSizedCanvas({
498538
if (!hoveredEvent || hoveredEvent.schedulingEvent !== schedulingEvent) {
499539
setHoveredEvent({
500540
componentMeasure: null,
501-
data,
502541
flamechartStackFrame: null,
503542
measure: null,
504543
nativeEvent: null,
544+
networkMeasure: null,
505545
schedulingEvent,
506546
snapshot: null,
507547
suspenseEvent: null,
@@ -517,10 +557,10 @@ function AutoSizedCanvas({
517557
if (!hoveredEvent || hoveredEvent.suspenseEvent !== suspenseEvent) {
518558
setHoveredEvent({
519559
componentMeasure: null,
520-
data,
521560
flamechartStackFrame: null,
522561
measure: null,
523562
nativeEvent: null,
563+
networkMeasure: null,
524564
schedulingEvent: null,
525565
snapshot: null,
526566
suspenseEvent,
@@ -536,10 +576,10 @@ function AutoSizedCanvas({
536576
if (!hoveredEvent || hoveredEvent.measure !== measure) {
537577
setHoveredEvent({
538578
componentMeasure: null,
539-
data,
540579
flamechartStackFrame: null,
541580
measure,
542581
nativeEvent: null,
582+
networkMeasure: null,
543583
schedulingEvent: null,
544584
snapshot: null,
545585
suspenseEvent: null,
@@ -558,10 +598,10 @@ function AutoSizedCanvas({
558598
) {
559599
setHoveredEvent({
560600
componentMeasure,
561-
data,
562601
flamechartStackFrame: null,
563602
measure: null,
564603
nativeEvent: null,
604+
networkMeasure: null,
565605
schedulingEvent: null,
566606
snapshot: null,
567607
suspenseEvent: null,
@@ -577,10 +617,10 @@ function AutoSizedCanvas({
577617
if (!hoveredEvent || hoveredEvent.snapshot !== snapshot) {
578618
setHoveredEvent({
579619
componentMeasure: null,
580-
data,
581620
flamechartStackFrame: null,
582621
measure: null,
583622
nativeEvent: null,
623+
networkMeasure: null,
584624
schedulingEvent: null,
585625
snapshot,
586626
suspenseEvent: null,
@@ -599,10 +639,10 @@ function AutoSizedCanvas({
599639
) {
600640
setHoveredEvent({
601641
componentMeasure: null,
602-
data,
603642
flamechartStackFrame,
604643
measure: null,
605644
nativeEvent: null,
645+
networkMeasure: null,
606646
schedulingEvent: null,
607647
snapshot: null,
608648
suspenseEvent: null,
@@ -611,53 +651,79 @@ function AutoSizedCanvas({
611651
}
612652
});
613653
}
654+
655+
const {current: networkMeasuresView} = networkMeasuresViewRef;
656+
if (networkMeasuresView) {
657+
networkMeasuresView.onHover = networkMeasure => {
658+
if (!hoveredEvent || hoveredEvent.networkMeasure !== networkMeasure) {
659+
setHoveredEvent({
660+
componentMeasure: null,
661+
flamechartStackFrame: null,
662+
measure: null,
663+
nativeEvent: null,
664+
networkMeasure,
665+
schedulingEvent: null,
666+
snapshot: null,
667+
suspenseEvent: null,
668+
userTimingMark: null,
669+
});
670+
}
671+
};
672+
}
614673
}, [
615674
hoveredEvent,
616675
data, // Attach onHover callbacks when views are re-created on data change
617676
]);
618677

619678
useLayoutEffect(() => {
620-
const {current: userTimingMarksView} = userTimingMarksViewRef;
679+
const userTimingMarksView = userTimingMarksViewRef.current;
621680
if (userTimingMarksView) {
622681
userTimingMarksView.setHoveredMark(
623682
hoveredEvent ? hoveredEvent.userTimingMark : null,
624683
);
625684
}
626685

627-
const {current: nativeEventsView} = nativeEventsViewRef;
686+
const nativeEventsView = nativeEventsViewRef.current;
628687
if (nativeEventsView) {
629688
nativeEventsView.setHoveredEvent(
630689
hoveredEvent ? hoveredEvent.nativeEvent : null,
631690
);
632691
}
633692

634-
const {current: schedulingEventsView} = schedulingEventsViewRef;
693+
const schedulingEventsView = schedulingEventsViewRef.current;
635694
if (schedulingEventsView) {
636695
schedulingEventsView.setHoveredEvent(
637696
hoveredEvent ? hoveredEvent.schedulingEvent : null,
638697
);
639698
}
640699

641-
const {current: suspenseEventsView} = suspenseEventsViewRef;
700+
const suspenseEventsView = suspenseEventsViewRef.current;
642701
if (suspenseEventsView) {
643702
suspenseEventsView.setHoveredEvent(
644703
hoveredEvent ? hoveredEvent.suspenseEvent : null,
645704
);
646705
}
647706

648-
const {current: reactMeasuresView} = reactMeasuresViewRef;
707+
const reactMeasuresView = reactMeasuresViewRef.current;
649708
if (reactMeasuresView) {
650709
reactMeasuresView.setHoveredMeasure(
651710
hoveredEvent ? hoveredEvent.measure : null,
652711
);
653712
}
654713

655-
const {current: flamechartView} = flamechartViewRef;
714+
const flamechartView = flamechartViewRef.current;
656715
if (flamechartView) {
657716
flamechartView.setHoveredFlamechartStackFrame(
658717
hoveredEvent ? hoveredEvent.flamechartStackFrame : null,
659718
);
660719
}
720+
721+
const networkMeasuresView = networkMeasuresViewRef.current;
722+
if (networkMeasuresView) {
723+
networkMeasuresView.setHoveredEvent(
724+
hoveredEvent ? hoveredEvent.networkMeasure : null,
725+
);
726+
}
661727
}, [hoveredEvent]);
662728

663729
// Draw to canvas in React's commit phase
@@ -677,6 +743,7 @@ function AutoSizedCanvas({
677743
componentMeasure,
678744
flamechartStackFrame,
679745
measure,
746+
networkMeasure,
680747
schedulingEvent,
681748
suspenseEvent,
682749
} = contextData.hoveredEvent;
@@ -689,6 +756,13 @@ function AutoSizedCanvas({
689756
Copy component name
690757
</ContextMenuItem>
691758
)}
759+
{networkMeasure !== null && (
760+
<ContextMenuItem
761+
onClick={() => copy(networkMeasure.url)}
762+
title="Copy URL">
763+
Copy URL
764+
</ContextMenuItem>
765+
)}
692766
{schedulingEvent !== null && (
693767
<ContextMenuItem
694768
onClick={() => copy(schedulingEvent.componentName)}

packages/react-devtools-scheduling-profiler/src/EventTooltip.css

+13-2
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
}
44

55
.TooltipSection,
6-
.TooltipWarningSection {
6+
.TooltipWarningSection,
7+
.SingleLineTextSection {
78
display: block;
89
border-radius: 0.125rem;
9-
max-width: 300px;
1010
padding: 0.25rem;
1111
user-select: none;
1212
pointer-events: none;
@@ -19,6 +19,13 @@
1919
margin-top: 0.25rem;
2020
background-color: var(--color-warning-background);
2121
}
22+
.TooltipSection,
23+
.TooltipWarningSection {
24+
max-width: 300px;
25+
}
26+
.SingleLineTextSection {
27+
white-space: nowrap;
28+
}
2229

2330
.Divider {
2431
height: 1px;
@@ -75,4 +82,8 @@
7582

7683
.Image {
7784
border: 1px solid var(--color-border);
85+
}
86+
87+
.DimText {
88+
color: var(--color-dim);
7889
}

0 commit comments

Comments
 (0)