@parca/profile 0.17.1 → 0.17.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/GraphTooltipArrow/Content.d.ts +1 -2
  3. package/dist/GraphTooltipArrow/Content.d.ts.map +1 -1
  4. package/dist/GraphTooltipArrow/Content.js +1 -2
  5. package/dist/GraphTooltipArrow/DockedGraphTooltip/index.d.ts +1 -2
  6. package/dist/GraphTooltipArrow/DockedGraphTooltip/index.d.ts.map +1 -1
  7. package/dist/GraphTooltipArrow/DockedGraphTooltip/index.js +1 -2
  8. package/dist/GraphTooltipArrow/useGraphTooltip/index.d.ts +1 -2
  9. package/dist/GraphTooltipArrow/useGraphTooltip/index.d.ts.map +1 -1
  10. package/dist/GraphTooltipArrow/useGraphTooltip/index.js +2 -2
  11. package/dist/ProfileIcicleGraph/IcicleGraphArrow/ContextMenu.d.ts +2 -6
  12. package/dist/ProfileIcicleGraph/IcicleGraphArrow/ContextMenu.d.ts.map +1 -1
  13. package/dist/ProfileIcicleGraph/IcicleGraphArrow/ContextMenu.js +4 -5
  14. package/dist/ProfileIcicleGraph/IcicleGraphArrow/ContextMenuWrapper.d.ts +20 -0
  15. package/dist/ProfileIcicleGraph/IcicleGraphArrow/ContextMenuWrapper.d.ts.map +1 -0
  16. package/{src/Callgraph/constants.ts → dist/ProfileIcicleGraph/IcicleGraphArrow/ContextMenuWrapper.js} +12 -3
  17. package/dist/ProfileIcicleGraph/IcicleGraphArrow/IcicleGraphNodes.d.ts +8 -51
  18. package/dist/ProfileIcicleGraph/IcicleGraphArrow/IcicleGraphNodes.d.ts.map +1 -1
  19. package/dist/ProfileIcicleGraph/IcicleGraphArrow/IcicleGraphNodes.js +59 -136
  20. package/dist/ProfileIcicleGraph/IcicleGraphArrow/MemoizedTooltip.d.ts +8 -0
  21. package/dist/ProfileIcicleGraph/IcicleGraphArrow/MemoizedTooltip.d.ts.map +1 -0
  22. package/dist/ProfileIcicleGraph/IcicleGraphArrow/MemoizedTooltip.js +40 -0
  23. package/dist/ProfileIcicleGraph/IcicleGraphArrow/TooltipContext.d.ts +32 -0
  24. package/dist/ProfileIcicleGraph/IcicleGraphArrow/TooltipContext.d.ts.map +1 -0
  25. package/dist/ProfileIcicleGraph/IcicleGraphArrow/TooltipContext.js +40 -0
  26. package/dist/ProfileIcicleGraph/IcicleGraphArrow/index.d.ts +4 -5
  27. package/dist/ProfileIcicleGraph/IcicleGraphArrow/index.d.ts.map +1 -1
  28. package/dist/ProfileIcicleGraph/IcicleGraphArrow/index.js +62 -76
  29. package/dist/ProfileIcicleGraph/IcicleGraphArrow/utils.d.ts +3 -3
  30. package/dist/ProfileIcicleGraph/IcicleGraphArrow/utils.d.ts.map +1 -1
  31. package/dist/ProfileIcicleGraph/IcicleGraphArrow/utils.js +9 -7
  32. package/dist/ProfileIcicleGraph/index.d.ts +3 -6
  33. package/dist/ProfileIcicleGraph/index.d.ts.map +1 -1
  34. package/dist/ProfileIcicleGraph/index.js +8 -17
  35. package/dist/ProfileView/components/DashboardItems/index.d.ts +3 -5
  36. package/dist/ProfileView/components/DashboardItems/index.d.ts.map +1 -1
  37. package/dist/ProfileView/components/DashboardItems/index.js +4 -9
  38. package/dist/ProfileView/components/Toolbars/index.d.ts.map +1 -1
  39. package/dist/ProfileView/components/Toolbars/index.js +1 -2
  40. package/dist/ProfileView/index.d.ts +1 -1
  41. package/dist/ProfileView/index.d.ts.map +1 -1
  42. package/dist/ProfileView/index.js +1 -13
  43. package/dist/ProfileView/types/visualization.d.ts +1 -1
  44. package/dist/ProfileView/types/visualization.d.ts.map +1 -1
  45. package/dist/index.d.ts +0 -4
  46. package/dist/index.d.ts.map +1 -1
  47. package/dist/index.js +0 -2
  48. package/dist/styles.css +1 -1
  49. package/package.json +5 -5
  50. package/src/GraphTooltipArrow/Content.tsx +0 -3
  51. package/src/GraphTooltipArrow/DockedGraphTooltip/index.tsx +0 -3
  52. package/src/GraphTooltipArrow/useGraphTooltip/index.ts +1 -3
  53. package/src/ProfileIcicleGraph/IcicleGraphArrow/ContextMenu.tsx +5 -13
  54. package/src/ProfileIcicleGraph/IcicleGraphArrow/ContextMenuWrapper.tsx +53 -0
  55. package/src/ProfileIcicleGraph/IcicleGraphArrow/IcicleGraphNodes.tsx +96 -310
  56. package/src/ProfileIcicleGraph/IcicleGraphArrow/MemoizedTooltip.tsx +78 -0
  57. package/src/ProfileIcicleGraph/IcicleGraphArrow/TooltipContext.tsx +93 -0
  58. package/src/ProfileIcicleGraph/IcicleGraphArrow/index.tsx +108 -216
  59. package/src/ProfileIcicleGraph/IcicleGraphArrow/utils.ts +8 -15
  60. package/src/ProfileIcicleGraph/index.tsx +7 -38
  61. package/src/ProfileView/components/DashboardItems/index.tsx +2 -27
  62. package/src/ProfileView/components/Toolbars/index.tsx +0 -2
  63. package/src/ProfileView/index.tsx +0 -14
  64. package/src/ProfileView/types/visualization.ts +1 -1
  65. package/src/index.tsx +0 -5
  66. package/dist/Callgraph/constants.d.ts +0 -3
  67. package/dist/Callgraph/constants.d.ts.map +0 -1
  68. package/dist/Callgraph/constants.js +0 -14
  69. package/dist/Callgraph/index.d.ts +0 -11
  70. package/dist/Callgraph/index.d.ts.map +0 -1
  71. package/dist/Callgraph/index.js +0 -104
  72. package/dist/Callgraph/mockData/index.d.ts +0 -149
  73. package/dist/Callgraph/mockData/index.d.ts.map +0 -1
  74. package/dist/Callgraph/mockData/index.js +0 -594
  75. package/dist/Callgraph/utils.d.ts +0 -20
  76. package/dist/Callgraph/utils.d.ts.map +0 -1
  77. package/dist/Callgraph/utils.js +0 -97
  78. package/dist/GraphTooltip/ExpandOnHoverValue.d.ts +0 -7
  79. package/dist/GraphTooltip/ExpandOnHoverValue.d.ts.map +0 -1
  80. package/dist/GraphTooltip/ExpandOnHoverValue.js +0 -4
  81. package/dist/GraphTooltip/index.d.ts +0 -41
  82. package/dist/GraphTooltip/index.d.ts.map +0 -1
  83. package/dist/GraphTooltip/index.js +0 -201
  84. package/dist/ProfileIcicleGraph/IcicleGraph/ColorStackLegend.d.ts +0 -6
  85. package/dist/ProfileIcicleGraph/IcicleGraph/ColorStackLegend.d.ts.map +0 -1
  86. package/dist/ProfileIcicleGraph/IcicleGraph/ColorStackLegend.js +0 -59
  87. package/dist/ProfileIcicleGraph/IcicleGraph/IcicleGraphNodes.d.ts +0 -47
  88. package/dist/ProfileIcicleGraph/IcicleGraph/IcicleGraphNodes.d.ts.map +0 -1
  89. package/dist/ProfileIcicleGraph/IcicleGraph/IcicleGraphNodes.js +0 -93
  90. package/dist/ProfileIcicleGraph/IcicleGraph/index.d.ts +0 -14
  91. package/dist/ProfileIcicleGraph/IcicleGraph/index.d.ts.map +0 -1
  92. package/dist/ProfileIcicleGraph/IcicleGraph/index.js +0 -48
  93. package/dist/ProfileIcicleGraph/IcicleGraph/useColoredGraph.d.ts +0 -15
  94. package/dist/ProfileIcicleGraph/IcicleGraph/useColoredGraph.d.ts.map +0 -1
  95. package/dist/ProfileIcicleGraph/IcicleGraph/useColoredGraph.js +0 -57
  96. package/dist/ProfileIcicleGraph/IcicleGraph/useNodeColor.d.ts +0 -8
  97. package/dist/ProfileIcicleGraph/IcicleGraph/useNodeColor.d.ts.map +0 -1
  98. package/dist/ProfileIcicleGraph/IcicleGraph/useNodeColor.js +0 -32
  99. package/dist/ProfileIcicleGraph/IcicleGraph/utils.d.ts +0 -7
  100. package/dist/ProfileIcicleGraph/IcicleGraph/utils.d.ts.map +0 -1
  101. package/dist/ProfileIcicleGraph/IcicleGraph/utils.js +0 -66
  102. package/dist/ProfileIcicleGraph/IcicleGraphArrow/IcicleChartRootNode.d.ts +0 -9
  103. package/dist/ProfileIcicleGraph/IcicleGraphArrow/IcicleChartRootNode.d.ts.map +0 -1
  104. package/dist/ProfileIcicleGraph/IcicleGraphArrow/IcicleChartRootNode.js +0 -45
  105. package/dist/ProfileView/hooks/useGraphviz.d.ts +0 -12
  106. package/dist/ProfileView/hooks/useGraphviz.d.ts.map +0 -1
  107. package/dist/ProfileView/hooks/useGraphviz.js +0 -42
  108. package/src/Callgraph/index.tsx +0 -177
  109. package/src/Callgraph/mockData/index.ts +0 -605
  110. package/src/Callgraph/utils.ts +0 -141
  111. package/src/GraphTooltip/ExpandOnHoverValue.tsx +0 -30
  112. package/src/GraphTooltip/index.tsx +0 -509
  113. package/src/ProfileIcicleGraph/IcicleGraph/ColorStackLegend.tsx +0 -96
  114. package/src/ProfileIcicleGraph/IcicleGraph/IcicleGraphNodes.tsx +0 -266
  115. package/src/ProfileIcicleGraph/IcicleGraph/index.tsx +0 -123
  116. package/src/ProfileIcicleGraph/IcicleGraph/useColoredGraph.ts +0 -117
  117. package/src/ProfileIcicleGraph/IcicleGraph/useNodeColor.ts +0 -54
  118. package/src/ProfileIcicleGraph/IcicleGraph/utils.ts +0 -102
  119. package/src/ProfileIcicleGraph/IcicleGraphArrow/IcicleChartRootNode.tsx +0 -130
  120. package/src/ProfileView/hooks/useGraphviz.ts +0 -69
@@ -11,7 +11,7 @@
11
11
  // See the License for the specific language governing permissions and
12
12
  // limitations under the License.
13
13
 
14
- import React, {memo, useCallback, useEffect, useMemo, useRef, useState} from 'react';
14
+ import React, {memo, useCallback, useMemo, useRef, useState} from 'react';
15
15
 
16
16
  import {Dictionary, Table, Vector, tableFromIPC} from 'apache-arrow';
17
17
  import {useContextMenu} from 'react-contexify';
@@ -19,26 +19,24 @@ import {useContextMenu} from 'react-contexify';
19
19
  import {FlamegraphArrow} from '@parca/client';
20
20
  import {useURLState} from '@parca/components';
21
21
  import {USER_PREFERENCES, useCurrentColorProfile, useUserPreference} from '@parca/hooks';
22
- import {ProfileType} from '@parca/parser';
23
- import {
24
- getColorForFeature,
25
- selectDarkMode,
26
- setHoveringNode,
27
- useAppDispatch,
28
- useAppSelector,
29
- } from '@parca/store';
30
- import {getLastItem, scaleLinear, type ColorConfig} from '@parca/utilities';
31
-
32
- import GraphTooltipArrow from '../../GraphTooltipArrow';
33
- import GraphTooltipArrowContent from '../../GraphTooltipArrow/Content';
34
- import {DockedGraphTooltip} from '../../GraphTooltipArrow/DockedGraphTooltip';
22
+ import {getColorForFeature, selectDarkMode, useAppSelector} from '@parca/store';
23
+ import {getLastItem, type ColorConfig} from '@parca/utilities';
24
+
35
25
  import {ProfileSource} from '../../ProfileSource';
36
26
  import {useProfileViewContext} from '../../ProfileView/context/ProfileViewContext';
37
- import ContextMenu from './ContextMenu';
38
- import {IcicleChartRootNode} from './IcicleChartRootNode';
27
+ import ContextMenuWrapper, {ContextMenuWrapperRef} from './ContextMenuWrapper';
39
28
  import {IcicleNode, RowHeight, colorByColors} from './IcicleGraphNodes';
29
+ import {MemoizedTooltip} from './MemoizedTooltip';
30
+ import {TooltipProvider} from './TooltipContext';
40
31
  import {useFilenamesList} from './useMappingList';
41
- import {CurrentPathFrame, arrowToString, extractFeature, extractFilenameFeature} from './utils';
32
+ import {
33
+ CurrentPathFrame,
34
+ arrowToString,
35
+ extractFeature,
36
+ extractFilenameFeature,
37
+ getCurrentPathFrameData,
38
+ isCurrentPathFrameMatch,
39
+ } from './utils';
42
40
 
43
41
  export const FIELD_LABELS_ONLY = 'labels_only';
44
42
  export const FIELD_MAPPING_FILE = 'mapping_file';
@@ -58,18 +56,18 @@ export const FIELD_LABELS = 'labels';
58
56
  export const FIELD_CUMULATIVE = 'cumulative';
59
57
  export const FIELD_FLAT = 'flat';
60
58
  export const FIELD_DIFF = 'diff';
59
+ export const FIELD_PARENT = 'parent';
60
+ export const FIELD_DEPTH = 'depth';
61
+ export const FIELD_VALUE_OFFSET = 'value_offset';
61
62
 
62
63
  interface IcicleGraphArrowProps {
63
64
  arrow: FlamegraphArrow;
64
65
  total: bigint;
65
66
  filtered: bigint;
66
- profileType?: ProfileType;
67
- profileSource?: ProfileSource;
67
+ profileSource: ProfileSource;
68
68
  width?: number;
69
69
  curPath: CurrentPathFrame[];
70
70
  setCurPath: (path: CurrentPathFrame[]) => void;
71
- sortBy: string;
72
- flamegraphLoading: boolean;
73
71
  isHalfScreen: boolean;
74
72
  mappingsListFromMetadata: string[];
75
73
  compareAbsolute: boolean;
@@ -113,32 +111,22 @@ export const IcicleGraphArrow = memo(function IcicleGraphArrow({
113
111
  width,
114
112
  setCurPath,
115
113
  curPath,
116
- profileType,
117
114
  profileSource,
118
- sortBy,
119
- flamegraphLoading,
120
115
  mappingsListFromMetadata,
121
116
  compareAbsolute,
122
117
  isIcicleChart = false,
123
118
  }: IcicleGraphArrowProps): React.JSX.Element {
124
- const [isContextMenuOpen, setIsContextMenuOpen] = useState<boolean>(false);
125
- const dispatch = useAppDispatch();
126
119
  const [highlightSimilarStacksPreference] = useUserPreference<boolean>(
127
120
  USER_PREFERENCES.HIGHLIGHT_SIMILAR_STACKS.key
128
121
  );
122
+ const [hoveringRow, setHoveringRow] = useState<number | undefined>(undefined);
129
123
  const [dockedMetainfo] = useUserPreference<boolean>(USER_PREFERENCES.GRAPH_METAINFO_DOCKED.key);
130
124
  const isDarkMode = useAppSelector(selectDarkMode);
131
125
 
132
126
  const table: Table<any> = useMemo(() => {
133
127
  return tableFromIPC(arrow.record);
134
128
  }, [arrow]);
135
-
136
- const [height, setHeight] = useState(0);
137
- const [hoveringRow, setHoveringRow] = useState<number | null>(null);
138
- const [hoveringLevel, setHoveringLevel] = useState<number | null>(null);
139
- const [hoveringName, setHoveringName] = useState<string | null>(null);
140
129
  const svg = useRef(null);
141
- const ref = useRef<SVGGElement>(null);
142
130
 
143
131
  const [binaryFrameFilter, setBinaryFrameFilter] = useURLState('binary_frame_filter');
144
132
 
@@ -200,29 +188,14 @@ export const IcicleGraphArrow = memo(function IcicleGraphArrow({
200
188
 
201
189
  const colorByColors: colorByColors = colorByList[colorByValue as ColorByKey];
202
190
 
203
- useEffect(() => {
204
- if (ref.current != null) {
205
- setHeight(ref?.current.getBoundingClientRect().height);
206
- }
207
- }, [width, flamegraphLoading]);
208
-
209
- const xScale = useMemo(() => {
210
- if (total === 0n) {
211
- return () => 0;
212
- }
213
-
214
- if (width === undefined) {
215
- return () => 0;
216
- }
217
- return scaleLinear([0n, total], [0, width]);
218
- }, [total, width]);
219
-
220
191
  const MENU_ID = 'icicle-graph-context-menu';
192
+ const contextMenuRef = useRef<ContextMenuWrapperRef>(null);
221
193
  const {show, hideAll} = useContextMenu({
222
194
  id: MENU_ID,
223
195
  });
224
196
  const displayMenu = useCallback(
225
- (e: React.MouseEvent): void => {
197
+ (e: React.MouseEvent, row: number): void => {
198
+ contextMenuRef.current?.setRow(row);
226
199
  show({
227
200
  event: e,
228
201
  });
@@ -230,10 +203,6 @@ export const IcicleGraphArrow = memo(function IcicleGraphArrow({
230
203
  [show]
231
204
  );
232
205
 
233
- const trackVisibility = (isVisible: boolean): void => {
234
- setIsContextMenuOpen(isVisible);
235
- };
236
-
237
206
  const hideBinary = (binaryToRemove: string): void => {
238
207
  // second/subsequent time filtering out a binary i.e. a binary has already been hidden
239
208
  // and we want to hide more binaries, we simply remove the binary from the binaryFrameFilter array in the URL.
@@ -249,187 +218,110 @@ export const IcicleGraphArrow = memo(function IcicleGraphArrow({
249
218
  setBinaryFrameFilter(newMappingsList);
250
219
  };
251
220
 
252
- const highlightSimilarStacksName = highlightSimilarStacksPreference ? hoveringName : null;
253
- const highlightSimilarStacksSetName = useMemo(() => {
254
- return highlightSimilarStacksPreference ? setHoveringName : noop;
255
- }, [highlightSimilarStacksPreference]);
256
- const highlightSimilarStacksRow = highlightSimilarStacksPreference ? hoveringRow : null;
257
- const path = useMemo(() => {
258
- return [];
259
- }, []);
260
-
261
- // useMemo for the root graph as it otherwise renders the whole graph if the hoveringRow changes.
262
- const root = useMemo(() => {
263
- if (isIcicleChart) {
264
- return (
221
+ const handleRowClick = (row: number): void => {
222
+ // Walk down the stack starting at row until we reach the root (row 0).
223
+ const path: CurrentPathFrame[] = [];
224
+ let currentRow = row;
225
+ while (currentRow > 0) {
226
+ const frame = getCurrentPathFrameData(table, currentRow);
227
+ path.push(frame);
228
+ currentRow = table.getChild(FIELD_PARENT)?.get(currentRow) ?? 0;
229
+ }
230
+
231
+ // Reverse the path so that the root is first.
232
+ path.reverse();
233
+ setCurPath(path);
234
+ };
235
+
236
+ const depthColumn = table.getChild(FIELD_DEPTH);
237
+ const maxDepth = depthColumn === null ? 0 : Math.max(...depthColumn.toArray());
238
+ const height = maxDepth * RowHeight;
239
+
240
+ // To find the selected row, we must walk the current path and look at which
241
+ // children of the current frame matches the path element exactly. Until the
242
+ // end, the row we find at the end is our selected row.
243
+ let currentRow = 0;
244
+ for (const frame of curPath) {
245
+ let childRows: number[] = Array.from(table.getChild(FIELD_CHILDREN)?.get(currentRow) ?? []);
246
+ if (childRows.length === 0) {
247
+ // If there are no children, we can stop here.
248
+ break;
249
+ }
250
+ childRows = childRows.filter(c => isCurrentPathFrameMatch(table, c, frame));
251
+ if (childRows.length === 0) {
252
+ // If there are no children that match the current path frame, we can stop here.
253
+ break;
254
+ }
255
+ if (childRows.length > 1) {
256
+ // If there are multiple children that match the current path frame, we can stop here.
257
+ // This is a case where the path is ambiguous and we cannot determine a single row.
258
+ break;
259
+ }
260
+ // If there is exactly one child that matches the current path frame, we can continue.
261
+ currentRow = childRows[0];
262
+ }
263
+ const selectedRow = currentRow;
264
+
265
+ return (
266
+ <TooltipProvider
267
+ table={table}
268
+ total={total}
269
+ totalUnfiltered={total + filtered}
270
+ unit={arrow.unit}
271
+ compareAbsolute={compareAbsolute}
272
+ >
273
+ <div className="relative">
274
+ <ContextMenuWrapper
275
+ ref={contextMenuRef}
276
+ menuId={MENU_ID}
277
+ table={table}
278
+ total={total}
279
+ totalUnfiltered={total + filtered}
280
+ compareAbsolute={compareAbsolute}
281
+ resetPath={() => setCurPath([])}
282
+ hideMenu={hideAll}
283
+ hideBinary={hideBinary}
284
+ unit={arrow.unit}
285
+ />
286
+ <MemoizedTooltip contextElement={svg.current} dockedMetainfo={dockedMetainfo} />
265
287
  <svg
266
288
  className="font-robotoMono"
267
289
  width={width}
268
290
  height={height}
269
291
  preserveAspectRatio="xMinYMid"
270
292
  ref={svg}
271
- onContextMenu={displayMenu}
272
293
  >
273
- <g ref={ref}>
274
- <g transform={'translate(0, 0)'}>
275
- <IcicleChartRootNode
276
- table={table}
277
- row={0}
278
- colors={colorByColors}
279
- colorBy={colorByValue}
280
- x={0}
281
- y={0}
282
- totalWidth={width ?? 1}
283
- height={RowHeight}
284
- setCurPath={setCurPath}
285
- curPath={curPath}
286
- total={total}
287
- xScale={xScale}
288
- path={path}
289
- level={0}
290
- isRoot={true}
291
- searchString={(currentSearchString as string) ?? ''}
292
- setHoveringRow={setHoveringRow}
293
- setHoveringLevel={setHoveringLevel}
294
- sortBy={sortBy}
295
- darkMode={isDarkMode}
296
- compareMode={compareMode}
297
- profileType={profileType}
298
- isContextMenuOpen={isContextMenuOpen}
299
- hoveringName={highlightSimilarStacksName}
300
- setHoveringName={highlightSimilarStacksSetName}
301
- hoveringRow={highlightSimilarStacksRow}
302
- colorForSimilarNodes={colorForSimilarNodes}
303
- highlightSimilarStacksPreference={highlightSimilarStacksPreference}
304
- profileSource={profileSource}
305
- />
306
- </g>
307
- </g>
308
- </svg>
309
- );
310
- }
311
- return (
312
- <svg
313
- className="font-robotoMono"
314
- width={width}
315
- height={height}
316
- preserveAspectRatio="xMinYMid"
317
- ref={svg}
318
- onContextMenu={displayMenu}
319
- >
320
- <g ref={ref}>
321
- <g transform={'translate(0, 0)'}>
294
+ {Array.from({length: table.numRows}, (_, row) => (
322
295
  <IcicleNode
296
+ key={row}
323
297
  table={table}
324
- row={0} // root is always row 0 in the arrow record
298
+ row={row} // root is always row 0 in the arrow record
325
299
  colors={colorByColors}
326
300
  colorBy={colorByValue}
327
- x={0}
328
- y={0}
329
301
  totalWidth={width ?? 1}
330
302
  height={RowHeight}
331
- setCurPath={setCurPath}
332
- curPath={curPath}
333
- total={total}
334
- xScale={xScale}
335
- path={path}
336
- level={0}
337
- isRoot={true}
338
303
  searchString={(currentSearchString as string) ?? ''}
339
- setHoveringRow={setHoveringRow}
340
- setHoveringLevel={setHoveringLevel}
341
- sortBy={sortBy}
342
304
  darkMode={isDarkMode}
343
305
  compareMode={compareMode}
344
- profileType={profileType}
345
- isContextMenuOpen={isContextMenuOpen}
346
- hoveringName={highlightSimilarStacksName}
347
- setHoveringName={highlightSimilarStacksSetName}
348
- hoveringRow={highlightSimilarStacksRow}
349
306
  colorForSimilarNodes={colorForSimilarNodes}
350
- highlightSimilarStacksPreference={highlightSimilarStacksPreference}
307
+ selectedRow={selectedRow}
308
+ onClick={() => {
309
+ if (isIcicleChart) {
310
+ // We don't want to expand in icicle charts.
311
+ return;
312
+ }
313
+ handleRowClick(row);
314
+ }}
315
+ onContextMenu={displayMenu}
316
+ hoveringRow={highlightSimilarStacksPreference ? hoveringRow : undefined}
317
+ setHoveringRow={highlightSimilarStacksPreference ? setHoveringRow : noop}
318
+ isIcicleChart={isIcicleChart}
319
+ profileSource={profileSource}
351
320
  />
352
- </g>
353
- </g>
354
- </svg>
355
- );
356
- }, [
357
- width,
358
- height,
359
- displayMenu,
360
- table,
361
- colorByColors,
362
- colorByValue,
363
- setCurPath,
364
- curPath,
365
- total,
366
- xScale,
367
- currentSearchString,
368
- sortBy,
369
- isDarkMode,
370
- compareMode,
371
- profileType,
372
- isContextMenuOpen,
373
- highlightSimilarStacksName,
374
- highlightSimilarStacksRow,
375
- colorForSimilarNodes,
376
- highlightSimilarStacksPreference,
377
- path,
378
- highlightSimilarStacksSetName,
379
- isIcicleChart,
380
- profileSource,
381
- ]);
382
-
383
- return (
384
- <>
385
- <div className="relative" onMouseLeave={() => dispatch(setHoveringNode(undefined))}>
386
- <ContextMenu
387
- menuId={MENU_ID}
388
- table={table}
389
- row={hoveringRow ?? 0}
390
- level={hoveringLevel ?? 0}
391
- total={total}
392
- totalUnfiltered={total + filtered}
393
- profileType={profileType}
394
- compareAbsolute={compareAbsolute}
395
- trackVisibility={trackVisibility}
396
- curPath={curPath}
397
- setCurPath={setCurPath}
398
- hideMenu={hideAll}
399
- hideBinary={hideBinary}
400
- unit={arrow.unit}
401
- />
402
- {dockedMetainfo ? (
403
- <DockedGraphTooltip
404
- table={table}
405
- row={hoveringRow}
406
- level={hoveringLevel ?? 0}
407
- total={total}
408
- totalUnfiltered={total + filtered}
409
- profileType={profileType}
410
- unit={arrow.unit}
411
- compareAbsolute={compareAbsolute}
412
- />
413
- ) : (
414
- !isContextMenuOpen && (
415
- <GraphTooltipArrow contextElement={svg.current} isContextMenuOpen={isContextMenuOpen}>
416
- <GraphTooltipArrowContent
417
- table={table}
418
- row={hoveringRow}
419
- level={hoveringLevel ?? 0}
420
- isFixed={false}
421
- total={total}
422
- totalUnfiltered={total + filtered}
423
- profileType={profileType}
424
- unit={arrow.unit}
425
- compareAbsolute={compareAbsolute}
426
- />
427
- </GraphTooltipArrow>
428
- )
429
- )}
430
- {root}
321
+ ))}
322
+ </svg>
431
323
  </div>
432
- </>
324
+ </TooltipProvider>
433
325
  );
434
326
  });
435
327
 
@@ -25,6 +25,7 @@ import {divide, getLastItem, valueFormatter} from '@parca/utilities';
25
25
  import {MergedProfileSource, ProfileSource} from '../../ProfileSource';
26
26
  import {BigIntDuo, hexifyAddress} from '../../utils';
27
27
  import {
28
+ FIELD_DEPTH,
28
29
  FIELD_FUNCTION_NAME,
29
30
  FIELD_FUNCTION_START_LINE,
30
31
  FIELD_INLINED,
@@ -33,14 +34,10 @@ import {
33
34
  FIELD_MAPPING_FILE,
34
35
  } from './index';
35
36
 
36
- export function nodeLabel(
37
- table: Table<any>,
38
- row: number,
39
- level: number,
40
- showBinaryName: boolean
41
- ): string {
37
+ export function nodeLabel(table: Table<any>, row: number, showBinaryName: boolean): string {
42
38
  const labelsOnly: boolean | null = table.getChild(FIELD_LABELS_ONLY)?.get(row);
43
- if (level === 1 && labelsOnly !== null && labelsOnly) {
39
+ const depth: number = table.getChild(FIELD_DEPTH)?.get(row) ?? 0;
40
+ if (depth === 1 && labelsOnly !== null && labelsOnly) {
44
41
  return getLabelSet(table, row);
45
42
  }
46
43
 
@@ -150,11 +147,7 @@ export interface CurrentPathFrame {
150
147
  labels?: string;
151
148
  }
152
149
 
153
- export const getCurrentPathFrameData = (
154
- table: Table<any>,
155
- row: number,
156
- level: number
157
- ): CurrentPathFrame => {
150
+ export const getCurrentPathFrameData = (table: Table<any>, row: number): CurrentPathFrame => {
158
151
  const functionName: string | null = arrowToString(table.getChild(FIELD_FUNCTION_NAME)?.get(row));
159
152
  const systemName: string | null = arrowToString(table.getChild(FIELD_FUNCTION_NAME)?.get(row));
160
153
  const fileName: string | null = arrowToString(table.getChild(FIELD_MAPPING_FILE)?.get(row));
@@ -163,8 +156,9 @@ export const getCurrentPathFrameData = (
163
156
  const address = hexifyAddress(addressBigInt);
164
157
  const inlined: boolean | null = table.getChild(FIELD_INLINED)?.get(row);
165
158
  const labelsOnly: boolean | null = table.getChild(FIELD_LABELS_ONLY)?.get(row);
159
+ const depth = table.getChild(FIELD_DEPTH)?.get(row) ?? 0;
166
160
  let labels: undefined | string;
167
- if (level === 1 && labelsOnly !== null && labelsOnly) {
161
+ if (depth === 1 && labelsOnly !== null && labelsOnly) {
168
162
  labels = getLabelSet(table, row);
169
163
  }
170
164
 
@@ -196,10 +190,9 @@ function getLabelSet(table: Table<any>, row: number): string {
196
190
  export function isCurrentPathFrameMatch(
197
191
  table: Table<any>,
198
192
  row: number,
199
- level: number,
200
193
  b: CurrentPathFrame
201
194
  ): boolean {
202
- const a = getCurrentPathFrameData(table, row, level);
195
+ const a = getCurrentPathFrameData(table, row);
203
196
  return (
204
197
  a.functionName === b.functionName &&
205
198
  a.systemName === b.systemName &&
@@ -16,7 +16,7 @@ import React, {LegacyRef, ReactNode, useEffect, useMemo, useState} from 'react';
16
16
  import {AnimatePresence, motion} from 'framer-motion';
17
17
  import {useMeasure} from 'react-use';
18
18
 
19
- import {Flamegraph, FlamegraphArrow} from '@parca/client';
19
+ import {FlamegraphArrow} from '@parca/client';
20
20
  import {IcicleGraphSkeleton, useParcaContext, useURLState} from '@parca/components';
21
21
  import {ProfileType} from '@parca/parser';
22
22
  import {capitalizeOnlyFirstLetter, divide} from '@parca/utilities';
@@ -25,7 +25,6 @@ import {MergedProfileSource, ProfileSource} from '../ProfileSource';
25
25
  import DiffLegend from '../ProfileView/components/DiffLegend';
26
26
  import {useProfileViewContext} from '../ProfileView/context/ProfileViewContext';
27
27
  import {TimelineGuide} from '../TimelineGuide';
28
- import {IcicleGraph} from './IcicleGraph';
29
28
  import {FIELD_FUNCTION_NAME, IcicleGraphArrow} from './IcicleGraphArrow';
30
29
  import useMappingList from './IcicleGraphArrow/useMappingList';
31
30
  import {CurrentPathFrame, boundsFromProfileSource} from './IcicleGraphArrow/utils';
@@ -36,14 +35,11 @@ export type ResizeHandler = (width: number, height: number) => void;
36
35
 
37
36
  interface ProfileIcicleGraphProps {
38
37
  width: number;
39
- graph?: Flamegraph;
40
38
  arrow?: FlamegraphArrow;
41
39
  total: bigint;
42
40
  filtered: bigint;
43
41
  profileType?: ProfileType;
44
- profileSource?: ProfileSource;
45
- curPath: string[] | [];
46
- setNewCurPath: (path: string[]) => void;
42
+ profileSource: ProfileSource;
47
43
  curPathArrow: CurrentPathFrame[] | [];
48
44
  setNewCurPathArrow: (path: CurrentPathFrame[]) => void;
49
45
  loading: boolean;
@@ -72,12 +68,9 @@ export const validateIcicleChartQuery = (
72
68
  };
73
69
 
74
70
  const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({
75
- graph,
76
71
  arrow,
77
72
  total,
78
73
  filtered,
79
- curPath,
80
- setNewCurPath,
81
74
  curPathArrow,
82
75
  setNewCurPathArrow,
83
76
  profileType,
@@ -96,7 +89,6 @@ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({
96
89
 
97
90
  const mappingsList = useMappingList(metadataMappingFiles);
98
91
 
99
- const [storeSortBy = FIELD_FUNCTION_NAME] = useURLState('sort_by');
100
92
  const [colorBy, setColorBy] = useURLState('color_by');
101
93
 
102
94
  // By default, we want delta profiles (CPU) to be relatively compared.
@@ -120,11 +112,11 @@ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({
120
112
  isFiltered,
121
113
  filteredPercentage,
122
114
  ] = useMemo(() => {
123
- if (graph === undefined && arrow === undefined) {
115
+ if (arrow === undefined) {
124
116
  return ['0', '0', false, '0', '0', false, '0', '0'];
125
117
  }
126
118
 
127
- const trimmed: bigint = graph?.trimmed ?? arrow?.trimmed ?? 0n;
119
+ const trimmed: bigint = arrow?.trimmed ?? 0n;
128
120
 
129
121
  const totalUnfiltered = total + filtered;
130
122
  // safeguard against division by zero
@@ -139,10 +131,9 @@ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({
139
131
  filtered > 0,
140
132
  numberFormatter.format(divide(total * 100n, totalUnfilteredDivisor)),
141
133
  ];
142
- }, [graph, arrow, filtered, total]);
134
+ }, [arrow, filtered, total]);
143
135
 
144
- const loadingState =
145
- !loading && (arrow !== undefined || graph !== undefined) && metadataMappingFiles !== undefined;
136
+ const loadingState = !loading && arrow !== undefined && metadataMappingFiles !== undefined;
146
137
 
147
138
  // If there is only one mapping file, we want to color by filename by default.
148
139
  useEffect(() => {
@@ -218,25 +209,11 @@ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({
218
209
  }
219
210
  }
220
211
 
221
- if (graph === undefined && arrow === undefined)
222
- return <div className="mx-auto text-center">No data...</div>;
212
+ if (arrow === undefined) return <div className="mx-auto text-center">No data...</div>;
223
213
 
224
214
  if (total === 0n && !loading)
225
215
  return <div className="mx-auto text-center">Profile has no samples</div>;
226
216
 
227
- if (graph !== undefined)
228
- return (
229
- <IcicleGraph
230
- width={width}
231
- graph={graph}
232
- total={total}
233
- filtered={filtered}
234
- curPath={curPath}
235
- setCurPath={setNewCurPath}
236
- profileType={profileType}
237
- />
238
- );
239
-
240
217
  if (arrow !== undefined) {
241
218
  return (
242
219
  <div className="relative">
@@ -258,9 +235,6 @@ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({
258
235
  filtered={filtered}
259
236
  curPath={curPathArrow}
260
237
  setCurPath={setNewCurPathArrow}
261
- profileType={profileType}
262
- sortBy={storeSortBy as string}
263
- flamegraphLoading={isLoading}
264
238
  isHalfScreen={isHalfScreen}
265
239
  mappingsListFromMetadata={mappingsList}
266
240
  compareAbsolute={isCompareAbsolute}
@@ -273,18 +247,13 @@ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({
273
247
  }
274
248
  }, [
275
249
  isLoading,
276
- graph,
277
250
  arrow,
278
251
  total,
279
252
  loading,
280
253
  width,
281
254
  filtered,
282
- curPath,
283
- setNewCurPath,
284
255
  curPathArrow,
285
256
  setNewCurPathArrow,
286
- profileType,
287
- storeSortBy,
288
257
  isHalfScreen,
289
258
  isDarkMode,
290
259
  mappingsList,