@parca/profile 0.17.2 → 0.17.4

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 -3
  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 -16
  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 +110 -213
  59. package/src/ProfileIcicleGraph/IcicleGraphArrow/utils.ts +8 -15
  60. package/src/ProfileIcicleGraph/index.tsx +7 -36
  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';
@@ -20,25 +20,24 @@ import {FlamegraphArrow} from '@parca/client';
20
20
  import {useURLState} from '@parca/components';
21
21
  import {USER_PREFERENCES, useCurrentColorProfile, useUserPreference} from '@parca/hooks';
22
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';
23
+ import {getColorForFeature, selectDarkMode, useAppSelector} from '@parca/store';
24
+ import {getLastItem, type ColorConfig} from '@parca/utilities';
25
+
35
26
  import {ProfileSource} from '../../ProfileSource';
36
27
  import {useProfileViewContext} from '../../ProfileView/context/ProfileViewContext';
37
- import ContextMenu from './ContextMenu';
38
- import {IcicleChartRootNode} from './IcicleChartRootNode';
28
+ import ContextMenuWrapper, {ContextMenuWrapperRef} from './ContextMenuWrapper';
39
29
  import {IcicleNode, RowHeight, colorByColors} from './IcicleGraphNodes';
30
+ import {MemoizedTooltip} from './MemoizedTooltip';
31
+ import {TooltipProvider} from './TooltipContext';
40
32
  import {useFilenamesList} from './useMappingList';
41
- import {CurrentPathFrame, arrowToString, extractFeature, extractFilenameFeature} from './utils';
33
+ import {
34
+ CurrentPathFrame,
35
+ arrowToString,
36
+ extractFeature,
37
+ extractFilenameFeature,
38
+ getCurrentPathFrameData,
39
+ isCurrentPathFrameMatch,
40
+ } from './utils';
42
41
 
43
42
  export const FIELD_LABELS_ONLY = 'labels_only';
44
43
  export const FIELD_MAPPING_FILE = 'mapping_file';
@@ -58,18 +57,19 @@ export const FIELD_LABELS = 'labels';
58
57
  export const FIELD_CUMULATIVE = 'cumulative';
59
58
  export const FIELD_FLAT = 'flat';
60
59
  export const FIELD_DIFF = 'diff';
60
+ export const FIELD_PARENT = 'parent';
61
+ export const FIELD_DEPTH = 'depth';
62
+ export const FIELD_VALUE_OFFSET = 'value_offset';
61
63
 
62
64
  interface IcicleGraphArrowProps {
63
65
  arrow: FlamegraphArrow;
64
66
  total: bigint;
65
67
  filtered: bigint;
66
68
  profileType?: ProfileType;
67
- profileSource?: ProfileSource;
69
+ profileSource: ProfileSource;
68
70
  width?: number;
69
71
  curPath: CurrentPathFrame[];
70
72
  setCurPath: (path: CurrentPathFrame[]) => void;
71
- sortBy: string;
72
- flamegraphLoading: boolean;
73
73
  isHalfScreen: boolean;
74
74
  mappingsListFromMetadata: string[];
75
75
  compareAbsolute: boolean;
@@ -115,30 +115,21 @@ export const IcicleGraphArrow = memo(function IcicleGraphArrow({
115
115
  curPath,
116
116
  profileType,
117
117
  profileSource,
118
- sortBy,
119
- flamegraphLoading,
120
118
  mappingsListFromMetadata,
121
119
  compareAbsolute,
122
120
  isIcicleChart = false,
123
121
  }: IcicleGraphArrowProps): React.JSX.Element {
124
- const [isContextMenuOpen, setIsContextMenuOpen] = useState<boolean>(false);
125
- const dispatch = useAppDispatch();
126
122
  const [highlightSimilarStacksPreference] = useUserPreference<boolean>(
127
123
  USER_PREFERENCES.HIGHLIGHT_SIMILAR_STACKS.key
128
124
  );
125
+ const [hoveringRow, setHoveringRow] = useState<number | undefined>(undefined);
129
126
  const [dockedMetainfo] = useUserPreference<boolean>(USER_PREFERENCES.GRAPH_METAINFO_DOCKED.key);
130
127
  const isDarkMode = useAppSelector(selectDarkMode);
131
128
 
132
129
  const table: Table<any> = useMemo(() => {
133
130
  return tableFromIPC(arrow.record);
134
131
  }, [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
132
  const svg = useRef(null);
141
- const ref = useRef<SVGGElement>(null);
142
133
 
143
134
  const [binaryFrameFilter, setBinaryFrameFilter] = useURLState('binary_frame_filter');
144
135
 
@@ -200,29 +191,14 @@ export const IcicleGraphArrow = memo(function IcicleGraphArrow({
200
191
 
201
192
  const colorByColors: colorByColors = colorByList[colorByValue as ColorByKey];
202
193
 
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
194
  const MENU_ID = 'icicle-graph-context-menu';
195
+ const contextMenuRef = useRef<ContextMenuWrapperRef>(null);
221
196
  const {show, hideAll} = useContextMenu({
222
197
  id: MENU_ID,
223
198
  });
224
199
  const displayMenu = useCallback(
225
- (e: React.MouseEvent): void => {
200
+ (e: React.MouseEvent, row: number): void => {
201
+ contextMenuRef.current?.setRow(row);
226
202
  show({
227
203
  event: e,
228
204
  });
@@ -230,10 +206,6 @@ export const IcicleGraphArrow = memo(function IcicleGraphArrow({
230
206
  [show]
231
207
  );
232
208
 
233
- const trackVisibility = (isVisible: boolean): void => {
234
- setIsContextMenuOpen(isVisible);
235
- };
236
-
237
209
  const hideBinary = (binaryToRemove: string): void => {
238
210
  // second/subsequent time filtering out a binary i.e. a binary has already been hidden
239
211
  // and we want to hide more binaries, we simply remove the binary from the binaryFrameFilter array in the URL.
@@ -249,187 +221,112 @@ export const IcicleGraphArrow = memo(function IcicleGraphArrow({
249
221
  setBinaryFrameFilter(newMappingsList);
250
222
  };
251
223
 
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 (
224
+ const handleRowClick = (row: number): void => {
225
+ // Walk down the stack starting at row until we reach the root (row 0).
226
+ const path: CurrentPathFrame[] = [];
227
+ let currentRow = row;
228
+ while (currentRow > 0) {
229
+ const frame = getCurrentPathFrameData(table, currentRow);
230
+ path.push(frame);
231
+ currentRow = table.getChild(FIELD_PARENT)?.get(currentRow) ?? 0;
232
+ }
233
+
234
+ // Reverse the path so that the root is first.
235
+ path.reverse();
236
+ setCurPath(path);
237
+ };
238
+
239
+ const depthColumn = table.getChild(FIELD_DEPTH);
240
+ const maxDepth = depthColumn === null ? 0 : Math.max(...depthColumn.toArray());
241
+ const height = maxDepth * RowHeight;
242
+
243
+ // To find the selected row, we must walk the current path and look at which
244
+ // children of the current frame matches the path element exactly. Until the
245
+ // end, the row we find at the end is our selected row.
246
+ let currentRow = 0;
247
+ for (const frame of curPath) {
248
+ let childRows: number[] = Array.from(table.getChild(FIELD_CHILDREN)?.get(currentRow) ?? []);
249
+ if (childRows.length === 0) {
250
+ // If there are no children, we can stop here.
251
+ break;
252
+ }
253
+ childRows = childRows.filter(c => isCurrentPathFrameMatch(table, c, frame));
254
+ if (childRows.length === 0) {
255
+ // If there are no children that match the current path frame, we can stop here.
256
+ break;
257
+ }
258
+ if (childRows.length > 1) {
259
+ // If there are multiple children that match the current path frame, we can stop here.
260
+ // This is a case where the path is ambiguous and we cannot determine a single row.
261
+ break;
262
+ }
263
+ // If there is exactly one child that matches the current path frame, we can continue.
264
+ currentRow = childRows[0];
265
+ }
266
+ const selectedRow = currentRow;
267
+
268
+ return (
269
+ <TooltipProvider
270
+ table={table}
271
+ total={total}
272
+ totalUnfiltered={total + filtered}
273
+ profileType={profileType}
274
+ unit={arrow.unit}
275
+ compareAbsolute={compareAbsolute}
276
+ >
277
+ <div className="relative">
278
+ <ContextMenuWrapper
279
+ ref={contextMenuRef}
280
+ menuId={MENU_ID}
281
+ table={table}
282
+ total={total}
283
+ totalUnfiltered={total + filtered}
284
+ compareAbsolute={compareAbsolute}
285
+ resetPath={() => setCurPath([])}
286
+ hideMenu={hideAll}
287
+ hideBinary={hideBinary}
288
+ unit={arrow.unit}
289
+ profileType={profileType}
290
+ />
291
+ <MemoizedTooltip contextElement={svg.current} dockedMetainfo={dockedMetainfo} />
265
292
  <svg
266
293
  className="font-robotoMono"
267
294
  width={width}
268
295
  height={height}
269
296
  preserveAspectRatio="xMinYMid"
270
297
  ref={svg}
271
- onContextMenu={displayMenu}
272
298
  >
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)'}>
299
+ {Array.from({length: table.numRows}, (_, row) => (
322
300
  <IcicleNode
301
+ key={row}
323
302
  table={table}
324
- row={0} // root is always row 0 in the arrow record
303
+ row={row} // root is always row 0 in the arrow record
325
304
  colors={colorByColors}
326
305
  colorBy={colorByValue}
327
- x={0}
328
- y={0}
329
306
  totalWidth={width ?? 1}
330
307
  height={RowHeight}
331
- setCurPath={setCurPath}
332
- curPath={curPath}
333
- total={total}
334
- xScale={xScale}
335
- path={path}
336
- level={0}
337
- isRoot={true}
338
308
  searchString={(currentSearchString as string) ?? ''}
339
- setHoveringRow={setHoveringRow}
340
- setHoveringLevel={setHoveringLevel}
341
- sortBy={sortBy}
342
309
  darkMode={isDarkMode}
343
310
  compareMode={compareMode}
344
- profileType={profileType}
345
- isContextMenuOpen={isContextMenuOpen}
346
- hoveringName={highlightSimilarStacksName}
347
- setHoveringName={highlightSimilarStacksSetName}
348
- hoveringRow={highlightSimilarStacksRow}
349
311
  colorForSimilarNodes={colorForSimilarNodes}
350
- highlightSimilarStacksPreference={highlightSimilarStacksPreference}
312
+ selectedRow={selectedRow}
313
+ onClick={() => {
314
+ if (isIcicleChart) {
315
+ // We don't want to expand in icicle charts.
316
+ return;
317
+ }
318
+ handleRowClick(row);
319
+ }}
320
+ onContextMenu={displayMenu}
321
+ hoveringRow={highlightSimilarStacksPreference ? hoveringRow : undefined}
322
+ setHoveringRow={highlightSimilarStacksPreference ? setHoveringRow : noop}
323
+ isIcicleChart={isIcicleChart}
324
+ profileSource={profileSource}
351
325
  />
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}
326
+ ))}
327
+ </svg>
431
328
  </div>
432
- </>
329
+ </TooltipProvider>
433
330
  );
434
331
  });
435
332
 
@@ -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">
@@ -259,8 +236,6 @@ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({
259
236
  curPath={curPathArrow}
260
237
  setCurPath={setNewCurPathArrow}
261
238
  profileType={profileType}
262
- sortBy={storeSortBy as string}
263
- flamegraphLoading={isLoading}
264
239
  isHalfScreen={isHalfScreen}
265
240
  mappingsListFromMetadata={mappingsList}
266
241
  compareAbsolute={isCompareAbsolute}
@@ -273,18 +248,14 @@ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({
273
248
  }
274
249
  }, [
275
250
  isLoading,
276
- graph,
277
251
  arrow,
278
252
  total,
279
253
  loading,
280
254
  width,
281
255
  filtered,
282
- curPath,
283
- setNewCurPath,
284
256
  curPathArrow,
285
257
  setNewCurPathArrow,
286
258
  profileType,
287
- storeSortBy,
288
259
  isHalfScreen,
289
260
  isDarkMode,
290
261
  mappingsList,