Skip to content
This repository was archived by the owner on Jun 26, 2020. It is now read-only.

Commit 68a272d

Browse files
authored
React Rally profiler feedback (#1100)
* Click in empty space of flamegraph/ranked chart to deselect an element * Added close/stop-inspecting button to fiber detail pane * Show unrounded durations on hover for chart tooltips * Make selected commit more prominent in snapshot selector * Left/right arrow keys navigate selected snapshot/commit * Snapshot selector auto-scrolls to ensure selected commit is visible * Snapshot selector shows filtered commit list when inspecting fiber durations * Tweaked selected snapshot style again to stand out more * Single click on arrow toggles tree open/closed * Moved 'show native elements?' option into new Profiler settings panel * "Commit time" -> "Committed at" * Left pad number to avoid reflow when stepping through snapshots * When dragging, don't leave the dragging state until you release the mouse. (Even if you mouse outside of the selector.) * Add control to filter commits below a thresold (ms) * Commit filtering applies to snapshot durations view as well
1 parent d0dd30d commit 68a272d

17 files changed

+753
-252
lines changed

frontend/Icons.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const Icons = {
1919
CHECK: `
2020
M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z
2121
`,
22-
CLEAR: `
22+
CLOSE: `
2323
M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41
2424
17.59 19 19 17.59 13.41 12z
2525
`,

frontend/Node.js

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -336,11 +336,14 @@ class Node extends React.Component<PropsType, StateType> {
336336
const jsxOpenTagStyle = jsxTagStyle(inverted && (!isBottomTagSelected || collapsed), nodeType, theme);
337337
const head = (
338338
<div ref={h => this._head = h} style={sharedHeadStyle} {...headEvents}>
339-
<span style={{
340-
width: '1rem',
341-
textAlign: 'center',
342-
marginLeft: '-1rem',
343-
}}>
339+
<span
340+
onClick={onToggleCollapse}
341+
style={{
342+
width: '1rem',
343+
textAlign: 'center',
344+
marginLeft: '-1rem',
345+
}}
346+
>
344347
{collapsed ? '▶' : '▼'}
345348
</span>
346349
&lt;

frontend/SvgIcon.js

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,23 @@ type Props = {
1717
style?: Object,
1818
};
1919

20-
const SvgIcon = ({ path, style = styles.svgIcon }: Props) => (
20+
const SvgIcon = ({ path, style }: Props) => (
2121
<svg
22-
style={style}
22+
style={{
23+
...DEFAULT_STYLE,
24+
...style,
25+
}}
2326
viewBox="0 0 24 24"
2427
>
2528
<path d={path}></path>
2629
</svg>
2730
);
2831

29-
const styles = {
30-
svgIcon: {
31-
flex: '0 0 1rem',
32-
width: '1rem',
33-
height: '1rem',
34-
fill: 'currentColor',
35-
},
32+
const DEFAULT_STYLE = {
33+
flex: '0 0 1rem',
34+
width: '1rem',
35+
height: '1rem',
36+
fill: 'currentColor',
3637
};
3738

3839
module.exports = SvgIcon;

plugins/Profiler/ProfilerStore.js

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,19 @@ const {EventEmitter} = require('events');
1818
const {get, set} = require('../../utils/storage');
1919

2020
const LOCAL_STORAGE_CHART_TYPE_KEY = 'profiler:selectedChartType';
21+
const LOCAL_STORAGE_COMMIT_THRESHOLD = 'profiler:commitThreshold';
22+
const LOCAL_STORAGE_HIDE_COMMITS_BELOW_THRESHOLD = 'profiler:hideCommitsBelowThreshold';
2123
const LOCAL_STORAGE_SHOW_NATIVE_NODES_KEY = 'profiler:showNativeNodes';
2224

2325
class ProfilerStore extends EventEmitter {
2426
_bridge: Bridge;
2527
_mainStore: Object;
2628

2729
cachedData = {};
30+
commitThreshold: number = ((get(LOCAL_STORAGE_COMMIT_THRESHOLD, 0): any): number);
31+
hideCommitsBelowThreshold: boolean = ((get(LOCAL_STORAGE_HIDE_COMMITS_BELOW_THRESHOLD, false): any): boolean);
2832
isRecording: boolean = false;
33+
isSettingsPanelActive: boolean = false;
2934
processedInteractions: {[id: string]: Interaction} = {};
3035
rootsToProfilerData: Map<string, RootProfilerData> = new Map();
3136
roots: List = new List();
@@ -86,6 +91,29 @@ class ProfilerStore extends EventEmitter {
8691
this.emit('roots', this._mainStore.roots);
8792
};
8893

94+
setCommitThrehsold = (commitThreshold: number) => {
95+
this.commitThreshold = commitThreshold;
96+
this.emit('commitThreshold', commitThreshold);
97+
set(LOCAL_STORAGE_COMMIT_THRESHOLD, commitThreshold);
98+
};
99+
100+
setHideCommitsBelowThreshold(hideCommitsBelowThreshold: boolean): void {
101+
this.hideCommitsBelowThreshold = hideCommitsBelowThreshold;
102+
this.emit('hideCommitsBelowThreshold', hideCommitsBelowThreshold);
103+
set(LOCAL_STORAGE_HIDE_COMMITS_BELOW_THRESHOLD, hideCommitsBelowThreshold);
104+
}
105+
106+
setIsRecording(isRecording: boolean): void {
107+
this.isRecording = isRecording;
108+
this.emit('isRecording', isRecording);
109+
this._mainStore.setIsRecording(isRecording);
110+
}
111+
112+
setIsSettingsPanelActive(isSettingsPanelActive: boolean): void {
113+
this.isSettingsPanelActive = isSettingsPanelActive;
114+
this.emit('isSettingsPanelActive', isSettingsPanelActive);
115+
}
116+
89117
setSelectedChartType(selectedChartType: ChartType) {
90118
this.selectedChartType = selectedChartType;
91119
this.emit('selectedChartType', selectedChartType);
@@ -98,12 +126,6 @@ class ProfilerStore extends EventEmitter {
98126
set(LOCAL_STORAGE_SHOW_NATIVE_NODES_KEY, showNativeNodes);
99127
}
100128

101-
setIsRecording(isRecording: boolean): void {
102-
this.isRecording = isRecording;
103-
this.emit('isRecording', isRecording);
104-
this._mainStore.setIsRecording(isRecording);
105-
}
106-
107129
storeSnapshot = () => {
108130
this._mainStore.snapshotQueue.forEach((snapshot: Snapshot) => {
109131
const { root } = snapshot;

plugins/Profiler/views/ChartNode.js

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,32 @@ type Props = {|
2424
onDoubleClick?: Function,
2525
placeLabelAboveNode?: boolean,
2626
theme: Theme,
27+
title: string,
2728
width: number,
2829
x: number,
2930
y: number,
3031
|};
3132

3233
const minWidthToDisplay = 35;
3334

34-
const ChartNode = ({ color, height, isDimmed = false, label, onClick, onDoubleClick, theme, width, x, y }: Props) => (
35+
const ChartNode = ({
36+
color,
37+
height,
38+
isDimmed = false,
39+
label,
40+
onClick,
41+
onDoubleClick,
42+
theme,
43+
title,
44+
width,
45+
x,
46+
y,
47+
}: Props) => (
3548
<g
3649
style={ChartAnimatedNode}
3750
transform={`translate(${x},${y})`}
3851
>
39-
<title>{label}</title>
52+
<title>{title}</title>
4053
<rect
4154
width={width}
4255
height={height}

plugins/Profiler/views/FiberRenderDurations.js

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import React, { PureComponent } from 'react';
1818
import AutoSizer from 'react-virtualized-auto-sizer';
1919
import { FixedSizeList as List } from 'react-window';
2020
import ChartNode from './ChartNode';
21-
import { minBarHeight, minBarWidth, getGradientColor, scale } from './constants';
21+
import { getFilteredSnapshotData, getGradientColor, minBarHeight, minBarWidth, scale } from './constants';
2222
import NoRenderTimesMessage from './NoRenderTimesMessage';
2323

2424
type Node = {|
@@ -46,40 +46,62 @@ type ItemData = {|
4646
type SelectSnapshot = (snapshot: Snapshot) => void;
4747

4848
type Props = {|
49+
commitThreshold: number,
50+
hideCommitsBelowThreshold: boolean,
4951
selectedFiberID: string,
5052
selectedSnapshot: Snapshot,
5153
selectSnapshot: SelectSnapshot,
54+
snapshotIndex: number,
5255
snapshots: Array<Snapshot>,
5356
stopInspecting: Function,
5457
theme: Theme,
5558
|};
5659

5760
export default ({
61+
commitThreshold,
62+
hideCommitsBelowThreshold,
5863
selectedFiberID,
5964
selectedSnapshot,
6065
selectSnapshot,
66+
snapshotIndex,
6167
snapshots,
6268
stopInspecting,
6369
theme,
64-
}: Props) => (
65-
<AutoSizer>
66-
{({ height, width }) => (
67-
<RenderDurations
68-
height={height}
69-
selectedFiberID={selectedFiberID}
70-
selectedSnapshot={selectedSnapshot}
71-
selectSnapshot={selectSnapshot}
72-
snapshots={snapshots}
73-
stopInspecting={stopInspecting}
74-
theme={theme}
75-
width={width}
76-
/>
77-
)}
78-
</AutoSizer>
79-
);
70+
}: Props) => {
71+
const filteredData = getFilteredSnapshotData(
72+
commitThreshold,
73+
hideCommitsBelowThreshold,
74+
true, // If we're viewing this component
75+
selectedFiberID,
76+
selectedSnapshot,
77+
snapshotIndex,
78+
snapshots,
79+
);
80+
81+
return (
82+
<AutoSizer>
83+
{({ height, width }) => (
84+
<RenderDurations
85+
commitThreshold={commitThreshold}
86+
height={height}
87+
hideCommitsBelowThreshold={hideCommitsBelowThreshold}
88+
selectedFiberID={selectedFiberID}
89+
selectedSnapshot={selectedSnapshot}
90+
selectSnapshot={selectSnapshot}
91+
snapshots={filteredData.snapshots}
92+
stopInspecting={stopInspecting}
93+
theme={theme}
94+
width={width}
95+
/>
96+
)}
97+
</AutoSizer>
98+
);
99+
};
80100

81101
type RenderDurationsProps = {|
102+
commitThreshold: number,
82103
height: number,
104+
hideCommitsBelowThreshold: boolean,
83105
selectedFiberID: string,
84106
selectedSnapshot: Snapshot,
85107
selectSnapshot: SelectSnapshot,
@@ -90,7 +112,9 @@ type RenderDurationsProps = {|
90112
|};
91113

92114
const RenderDurations = ({
115+
commitThreshold,
93116
height,
117+
hideCommitsBelowThreshold,
94118
selectedFiberID,
95119
selectedSnapshot,
96120
selectSnapshot,
@@ -111,7 +135,9 @@ const RenderDurations = ({
111135
if (maxValue === 0) {
112136
return (
113137
<NoRenderTimesMessage
138+
commitThreshold={commitThreshold}
114139
height={height}
140+
hideCommitsBelowThreshold={hideCommitsBelowThreshold}
115141
stopInspecting={stopInspecting}
116142
width={width}
117143
/>
@@ -171,6 +197,7 @@ class ListItem extends PureComponent<any, void> {
171197
onClick={() => selectSnapshot(node.parentSnapshot)}
172198
onDoubleClick={stopInspecting}
173199
theme={theme}
200+
title={`${node.value}ms`}
174201
width={width}
175202
x={left}
176203
y={height - safeHeight}

plugins/Profiler/views/IconButton.js

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,29 @@ const IconButton = Hoverable(
2222
onMouseEnter={onMouseEnter}
2323
onMouseLeave={onMouseLeave}
2424
style={{
25+
position: 'relative',
26+
width: '1.5rem',
27+
height: '1.5rem',
2528
background: isTransparent ? 'none' : theme.base00,
2629
border: 'none',
30+
borderRadius: '0.125rem',
2731
outline: 'none',
2832
cursor: disabled ? 'default' : 'pointer',
2933
color: isActive ? theme.state00 : (isHovered ? theme.state06 : theme.base05),
3034
opacity: disabled ? 0.5 : 1,
31-
padding: '4px',
3235
...style,
3336
}}
3437
title={title}
3538
>
36-
<SvgIcon path={icon} />
39+
<SvgIcon
40+
path={icon}
41+
style={{
42+
position: 'absolute',
43+
top: '50%',
44+
bottom: '50%',
45+
transform: 'translate(-50%, -50%)',
46+
}}
47+
/>
3748
</button>
3849
)
3950
);

plugins/Profiler/views/NoRenderTimesMessage.js

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,20 @@ import React from 'react';
1414
import {sansSerif} from '../../../frontend/Themes/Fonts';
1515

1616
type Props = {|
17+
commitThreshold: number,
1718
height: number,
19+
hideCommitsBelowThreshold: boolean,
1820
stopInspecting: Function,
1921
width: number,
2022
|};
2123

22-
export default ({ height, stopInspecting, width }: Props) => (
24+
export default ({
25+
commitThreshold,
26+
height,
27+
hideCommitsBelowThreshold,
28+
stopInspecting,
29+
width,
30+
}: Props) => (
2331
<div style={{
2432
display: 'flex',
2533
flexDirection: 'column',
@@ -29,11 +37,16 @@ export default ({ height, stopInspecting, width }: Props) => (
2937
height,
3038
width,
3139
}}>
32-
<p style={{
33-
fontSize: sansSerif.sizes.large,
34-
}}>
35-
No render times were recorded for the selected element
36-
</p>
40+
{!hideCommitsBelowThreshold && (
41+
<p style={{ fontSize: sansSerif.sizes.large}}>
42+
No render times were recorded for the selected element.
43+
</p>
44+
)}
45+
{hideCommitsBelowThreshold && (
46+
<p style={{ fontSize: sansSerif.sizes.large}}>
47+
No render times were recorded for the selected element based on the current commit threshold.
48+
</p>
49+
)}
3750
<p>
3851
<button onClick={stopInspecting}>Return to the previous view</button>
3952
</p>

0 commit comments

Comments
 (0)