@parca/profile 0.19.51 → 0.19.53

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 (35) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/ProfileExplorer/index.js +3 -3
  3. package/dist/ProfileFlameGraph/FlameGraphArrow/FlameGraphNodes.js +4 -3
  4. package/dist/ProfileFlameGraph/FlameGraphArrow/index.d.ts +2 -0
  5. package/dist/ProfileFlameGraph/FlameGraphArrow/index.d.ts.map +1 -1
  6. package/dist/ProfileFlameGraph/FlameGraphArrow/index.js +7 -36
  7. package/dist/ProfileFlameGraph/index.d.ts +1 -1
  8. package/dist/ProfileFlameGraph/index.d.ts.map +1 -1
  9. package/dist/ProfileFlameGraph/index.js +14 -6
  10. package/dist/ProfileView/components/DashboardItems/index.d.ts +0 -2
  11. package/dist/ProfileView/components/DashboardItems/index.d.ts.map +1 -1
  12. package/dist/ProfileView/components/ProfileFilters/useProfileFilters.d.ts.map +1 -1
  13. package/dist/ProfileView/components/ProfileFilters/useProfileFilters.js +10 -4
  14. package/dist/ProfileView/hooks/useResetFlameGraphState.d.ts +2 -0
  15. package/dist/ProfileView/hooks/useResetFlameGraphState.d.ts.map +1 -0
  16. package/dist/ProfileView/hooks/{useResetStateOnNewSearch.js → useResetFlameGraphState.js} +1 -1
  17. package/dist/ProfileView/hooks/useVisualizationState.d.ts +0 -2
  18. package/dist/ProfileView/hooks/useVisualizationState.d.ts.map +1 -1
  19. package/dist/ProfileView/hooks/useVisualizationState.js +5 -5
  20. package/dist/ProfileView/index.d.ts.map +1 -1
  21. package/dist/ProfileView/index.js +1 -3
  22. package/dist/ProfileViewWithData.js +1 -1
  23. package/package.json +11 -11
  24. package/src/ProfileExplorer/index.tsx +3 -3
  25. package/src/ProfileFlameGraph/FlameGraphArrow/FlameGraphNodes.tsx +4 -4
  26. package/src/ProfileFlameGraph/FlameGraphArrow/index.tsx +13 -42
  27. package/src/ProfileFlameGraph/index.tsx +15 -5
  28. package/src/ProfileView/components/DashboardItems/index.tsx +0 -2
  29. package/src/ProfileView/components/ProfileFilters/useProfileFilters.ts +10 -4
  30. package/src/ProfileView/hooks/{useResetStateOnNewSearch.ts → useResetFlameGraphState.ts} +1 -1
  31. package/src/ProfileView/hooks/useVisualizationState.ts +6 -7
  32. package/src/ProfileView/index.tsx +0 -4
  33. package/src/ProfileViewWithData.tsx +1 -1
  34. package/dist/ProfileView/hooks/useResetStateOnNewSearch.d.ts +0 -2
  35. package/dist/ProfileView/hooks/useResetStateOnNewSearch.d.ts.map +0 -1
package/CHANGELOG.md CHANGED
@@ -3,6 +3,18 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [0.19.53](https://github.com/parca-dev/parca/compare/@parca/profile@0.19.52...@parca/profile@0.19.53) (2025-09-15)
7
+
8
+ ## 0.24.2 (2025-09-10)
9
+
10
+ **Note:** Version bump only for package @parca/profile
11
+
12
+ ## 0.19.52 (2025-09-15)
13
+
14
+ ## 0.24.2 (2025-09-10)
15
+
16
+ **Note:** Version bump only for package @parca/profile
17
+
6
18
  ## 0.19.51 (2025-09-10)
7
19
 
8
20
  ## 0.24.1 (2025-09-09)
@@ -19,7 +19,7 @@ import { createStore } from '@parca/store';
19
19
  import { capitalizeOnlyFirstLetter, safeDecode } from '@parca/utilities';
20
20
  import { ProfileSelectionFromParams, SuffixParams } from '..';
21
21
  import { useProfileTypes } from '../ProfileSelector';
22
- import { useResetStateOnNewSearch } from '../ProfileView/hooks/useResetStateOnNewSearch';
22
+ import { useResetFlameGraphState } from '../ProfileView/hooks/useResetFlameGraphState';
23
23
  import { useResetStateOnProfileTypeChange } from '../ProfileView/hooks/useResetStateOnProfileTypeChange';
24
24
  import { sumByToParam, useSumByFromParams } from '../useSumBy';
25
25
  import ProfileExplorerCompare from './ProfileExplorerCompare';
@@ -89,7 +89,7 @@ const ProfileExplorerApp = ({ queryClient, queryParams, navigateTo, }) => {
89
89
  const [profileA, setProfileA] = useState(null);
90
90
  const [profileB, setProfileB] = useState(null);
91
91
  const resetStateOnProfileTypeChange = useResetStateOnProfileTypeChange();
92
- const resetStateOnNewSearch = useResetStateOnNewSearch();
92
+ const resetFlameGraphState = useResetFlameGraphState();
93
93
  const sumByA = useSumByFromParams(sum_by_a);
94
94
  const sumByB = useSumByFromParams(sum_by_b);
95
95
  useEffect(() => {
@@ -156,7 +156,7 @@ const ProfileExplorerApp = ({ queryClient, queryParams, navigateTo, }) => {
156
156
  }
157
157
  else {
158
158
  // Reset the state when a new search is performed.
159
- resetStateOnNewSearch();
159
+ resetFlameGraphState();
160
160
  }
161
161
  }
162
162
  const mergeParams = q.mergeFrom !== undefined && q.mergeTo !== undefined
@@ -51,7 +51,6 @@ export const FlameNode = React.memo(function FlameNodeNoMemo({ table, row, color
51
51
  ? BigInt(valueOffsetColumn?.get(row))
52
52
  : 0n;
53
53
  const colorAttribute = colorBy === 'filename' ? filename : colorBy === 'binary' ? mappingFile : null;
54
- const colorsMap = colors;
55
54
  const hoveringName = hoveringRow !== undefined ? arrowToString(functionNameColumn?.get(hoveringRow)) : '';
56
55
  const shouldBeHighlighted = functionName != null && hoveringName != null && functionName === hoveringName;
57
56
  const colorResult = useNodeColor({
@@ -59,7 +58,7 @@ export const FlameNode = React.memo(function FlameNodeNoMemo({ table, row, color
59
58
  compareMode,
60
59
  cumulative,
61
60
  diff,
62
- colorsMap,
61
+ colorsMap: colors,
63
62
  colorAttribute,
64
63
  });
65
64
  const name = useMemo(() => {
@@ -138,5 +137,7 @@ export const FlameNode = React.memo(function FlameNodeNoMemo({ table, row, color
138
137
  prevProps.hoveringRow === nextProps.hoveringRow &&
139
138
  prevProps.totalWidth === nextProps.totalWidth &&
140
139
  prevProps.height === nextProps.height &&
141
- prevProps.effectiveDepth === nextProps.effectiveDepth);
140
+ prevProps.effectiveDepth === nextProps.effectiveDepth &&
141
+ prevProps.colorBy === nextProps.colorBy &&
142
+ prevProps.colors === nextProps.colors);
142
143
  });
@@ -37,6 +37,8 @@ interface FlameGraphArrowProps {
37
37
  setCurPath: (path: CurrentPathFrame[]) => void;
38
38
  isHalfScreen: boolean;
39
39
  mappingsListFromMetadata: string[];
40
+ filenamesListFromMetadata: string[];
41
+ colorBy: string;
40
42
  compareAbsolute: boolean;
41
43
  isFlameChart?: boolean;
42
44
  isRenderedAsFlamegraph?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ProfileFlameGraph/FlameGraphArrow/index.tsx"],"names":[],"mappings":"AAaA,OAAO,KAQN,MAAM,OAAO,CAAC;AAKf,OAAO,EAAC,eAAe,EAAC,MAAM,eAAe,CAAC;AAG9C,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;AAE1C,OAAO,EAAc,KAAK,WAAW,EAAC,MAAM,kBAAkB,CAAC;AAE/D,OAAO,EAAC,aAAa,EAAC,MAAM,qBAAqB,CAAC;AAIlD,OAAO,EAAuB,aAAa,EAAC,MAAM,mBAAmB,CAAC;AAMtE,OAAO,EACL,gBAAgB,EAOjB,MAAM,SAAS,CAAC;AAEjB,eAAO,MAAM,iBAAiB,gBAAgB,CAAC;AAC/C,eAAO,MAAM,kBAAkB,iBAAiB,CAAC;AACjD,eAAO,MAAM,sBAAsB,qBAAqB,CAAC;AACzD,eAAO,MAAM,sBAAsB,qBAAqB,CAAC;AACzD,eAAO,MAAM,mBAAmB,kBAAkB,CAAC;AACnD,eAAO,MAAM,aAAa,YAAY,CAAC;AACvC,eAAO,MAAM,eAAe,cAAc,CAAC;AAC3C,eAAO,MAAM,cAAc,aAAa,CAAC;AACzC,eAAO,MAAM,sBAAsB,qBAAqB,CAAC;AACzD,eAAO,MAAM,mBAAmB,kBAAkB,CAAC;AACnD,eAAO,MAAM,0BAA0B,yBAAyB,CAAC;AACjE,eAAO,MAAM,wBAAwB,uBAAuB,CAAC;AAC7D,eAAO,MAAM,yBAAyB,uBAAuB,CAAC;AAC9D,eAAO,MAAM,cAAc,aAAa,CAAC;AACzC,eAAO,MAAM,YAAY,WAAW,CAAC;AACrC,eAAO,MAAM,gBAAgB,eAAe,CAAC;AAC7C,eAAO,MAAM,UAAU,SAAS,CAAC;AACjC,eAAO,MAAM,UAAU,SAAS,CAAC;AACjC,eAAO,MAAM,YAAY,WAAW,CAAC;AACrC,eAAO,MAAM,WAAW,UAAU,CAAC;AACnC,eAAO,MAAM,kBAAkB,iBAAiB,CAAC;AAEjD,UAAU,oBAAoB;IAC5B,KAAK,EAAE,eAAe,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,aAAa,EAAE,aAAa,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,UAAU,EAAE,CAAC,IAAI,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IAC/C,YAAY,EAAE,OAAO,CAAC;IACtB,wBAAwB,EAAE,MAAM,EAAE,CAAC;IACnC,eAAe,EAAE,OAAO,CAAC;IACzB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,eAAO,MAAM,gBAAgB,GAC3B,cAAc,MAAM,EAAE,EACtB,YAAY,OAAO,EACnB,qBAAqB,WAAW,KAC/B,aAQF,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC5B,eAAe,MAAM,EAAE,EACvB,YAAY,OAAO,EACnB,qBAAqB,WAAW,KAC/B,aAQF,CAAC;AAIF,eAAO,MAAM,eAAe,kDAuR1B,CAAC;AAEH,eAAe,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ProfileFlameGraph/FlameGraphArrow/index.tsx"],"names":[],"mappings":"AAaA,OAAO,KAQN,MAAM,OAAO,CAAC;AAKf,OAAO,EAAC,eAAe,EAAC,MAAM,eAAe,CAAC;AAG9C,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;AAE1C,OAAO,EAAC,KAAK,WAAW,EAAC,MAAM,kBAAkB,CAAC;AAElD,OAAO,EAAC,aAAa,EAAC,MAAM,qBAAqB,CAAC;AAIlD,OAAO,EAAuB,aAAa,EAAC,MAAM,mBAAmB,CAAC;AAKtE,OAAO,EACL,gBAAgB,EAMjB,MAAM,SAAS,CAAC;AAEjB,eAAO,MAAM,iBAAiB,gBAAgB,CAAC;AAC/C,eAAO,MAAM,kBAAkB,iBAAiB,CAAC;AACjD,eAAO,MAAM,sBAAsB,qBAAqB,CAAC;AACzD,eAAO,MAAM,sBAAsB,qBAAqB,CAAC;AACzD,eAAO,MAAM,mBAAmB,kBAAkB,CAAC;AACnD,eAAO,MAAM,aAAa,YAAY,CAAC;AACvC,eAAO,MAAM,eAAe,cAAc,CAAC;AAC3C,eAAO,MAAM,cAAc,aAAa,CAAC;AACzC,eAAO,MAAM,sBAAsB,qBAAqB,CAAC;AACzD,eAAO,MAAM,mBAAmB,kBAAkB,CAAC;AACnD,eAAO,MAAM,0BAA0B,yBAAyB,CAAC;AACjE,eAAO,MAAM,wBAAwB,uBAAuB,CAAC;AAC7D,eAAO,MAAM,yBAAyB,uBAAuB,CAAC;AAC9D,eAAO,MAAM,cAAc,aAAa,CAAC;AACzC,eAAO,MAAM,YAAY,WAAW,CAAC;AACrC,eAAO,MAAM,gBAAgB,eAAe,CAAC;AAC7C,eAAO,MAAM,UAAU,SAAS,CAAC;AACjC,eAAO,MAAM,UAAU,SAAS,CAAC;AACjC,eAAO,MAAM,YAAY,WAAW,CAAC;AACrC,eAAO,MAAM,WAAW,UAAU,CAAC;AACnC,eAAO,MAAM,kBAAkB,iBAAiB,CAAC;AAEjD,UAAU,oBAAoB;IAC5B,KAAK,EAAE,eAAe,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,aAAa,EAAE,aAAa,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,UAAU,EAAE,CAAC,IAAI,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IAC/C,YAAY,EAAE,OAAO,CAAC;IACtB,wBAAwB,EAAE,MAAM,EAAE,CAAC;IACnC,yBAAyB,EAAE,MAAM,EAAE,CAAC;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,OAAO,CAAC;IACzB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,eAAO,MAAM,gBAAgB,GAC3B,cAAc,MAAM,EAAE,EACtB,YAAY,OAAO,EACnB,qBAAqB,WAAW,KAC/B,aAQF,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC5B,eAAe,MAAM,EAAE,EACvB,YAAY,OAAO,EACnB,qBAAqB,WAAW,KAC/B,aAQF,CAAC;AAIF,eAAO,MAAM,eAAe,kDA0P1B,CAAC;AAEH,eAAe,eAAe,CAAC"}
@@ -14,20 +14,18 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
14
14
  import { memo, useCallback, useDeferredValue, useEffect, useMemo, useRef, useState, } from 'react';
15
15
  import { tableFromIPC } from 'apache-arrow';
16
16
  import { useContextMenu } from 'react-contexify';
17
- import { useParcaContext, useURLState } from '@parca/components';
17
+ import { useParcaContext } from '@parca/components';
18
18
  import { USER_PREFERENCES, useCurrentColorProfile, useUserPreference } from '@parca/hooks';
19
19
  import { getColorForFeature, selectDarkMode, useAppSelector } from '@parca/store';
20
- import { getLastItem } from '@parca/utilities';
21
20
  import { useProfileFilters } from '../../ProfileView/components/ProfileFilters/useProfileFilters';
22
21
  import { useProfileViewContext } from '../../ProfileView/context/ProfileViewContext';
23
22
  import ContextMenuWrapper from './ContextMenuWrapper';
24
23
  import { FlameNode, RowHeight } from './FlameGraphNodes';
25
24
  import { MemoizedTooltip } from './MemoizedTooltip';
26
25
  import { TooltipProvider } from './TooltipContext';
27
- import { useFilenamesList } from './useMappingList';
28
26
  import { useScrollViewport } from './useScrollViewport';
29
27
  import { useVisibleNodes } from './useVisibleNodes';
30
- import { arrowToString, extractFeature, extractFilenameFeature, getCurrentPathFrameData, getMaxDepth, isCurrentPathFrameMatch, } from './utils';
28
+ import { extractFeature, extractFilenameFeature, getCurrentPathFrameData, getMaxDepth, isCurrentPathFrameMatch, } from './utils';
31
29
  export const FIELD_LABELS_ONLY = 'labels_only';
32
30
  export const FIELD_MAPPING_FILE = 'mapping_file';
33
31
  export const FIELD_MAPPING_BUILD_ID = 'mapping_build_id';
@@ -66,7 +64,7 @@ export const getFilenameColors = (filenamesList, isDarkMode, currentColorProfile
66
64
  return colors;
67
65
  };
68
66
  const noop = () => { };
69
- export const FlameGraphArrow = memo(function FlameGraphArrow({ arrow, total, filtered, width, setCurPath, curPath, profileType, profileSource, compareAbsolute, isFlameChart = false, isRenderedAsFlamegraph = false, isInSandwichView = false, tooltipId = 'default', maxFrameCount, isExpanded = false, }) {
67
+ export const FlameGraphArrow = memo(function FlameGraphArrow({ arrow, total, filtered, width, setCurPath, curPath, profileType, profileSource, compareAbsolute, isFlameChart = false, isRenderedAsFlamegraph = false, isInSandwichView = false, tooltipId = 'default', maxFrameCount, isExpanded = false, mappingsListFromMetadata, filenamesListFromMetadata, colorBy, }) {
70
68
  const [highlightSimilarStacksPreference] = useUserPreference(USER_PREFERENCES.HIGHLIGHT_SIMILAR_STACKS.key);
71
69
  const [hoveringRow, setHoveringRow] = useState(undefined);
72
70
  const [dockedMetainfo] = useUserPreference(USER_PREFERENCES.GRAPH_METAINFO_DOCKED.key);
@@ -87,42 +85,15 @@ export const FlameGraphArrow = memo(function FlameGraphArrow({ arrow, total, fil
87
85
  const { compareMode } = useProfileViewContext();
88
86
  const currentColorProfile = useCurrentColorProfile();
89
87
  const colorForSimilarNodes = currentColorProfile.colorForSimilarNodes;
90
- const [colorBy, _] = useURLState('color_by');
91
88
  const colorByValue = colorBy === undefined || colorBy === '' ? 'binary' : colorBy;
92
- const filenamesList = useFilenamesList(table);
93
- const mappingsList = useMemo(() => {
94
- // Read the mappings from the dictionary that contains all mapping strings.
95
- // This is great, as might only have a dozen or so mappings,
96
- // and don't need to read through all the rows (potentially thousands).
97
- const mappingsDict = table.getChild(FIELD_MAPPING_FILE);
98
- const mappings = mappingsDict?.data
99
- .map(mapping => {
100
- if (mapping.dictionary == null) {
101
- return [];
102
- }
103
- const len = mapping.dictionary.length;
104
- const entries = [];
105
- for (let i = 0; i < len; i++) {
106
- const fn = arrowToString(mapping.dictionary.get(i));
107
- entries.push(getLastItem(fn) ?? '');
108
- }
109
- return entries;
110
- })
111
- .flat() ?? [];
112
- // We add a EVERYTHING ELSE mapping to the list.
113
- mappings.push('');
114
- // We sort the mappings alphabetically to make sure that the order is always the same.
115
- mappings.sort((a, b) => a.localeCompare(b));
116
- return mappings;
117
- }, [table]);
118
89
  const filenameColors = useMemo(() => {
119
- const colors = getFilenameColors(filenamesList, isDarkMode, currentColorProfile);
90
+ const colors = getFilenameColors(filenamesListFromMetadata, isDarkMode, currentColorProfile);
120
91
  return colors;
121
- }, [isDarkMode, filenamesList, currentColorProfile]);
92
+ }, [isDarkMode, filenamesListFromMetadata, currentColorProfile]);
122
93
  const mappingColors = useMemo(() => {
123
- const colors = getMappingColors(mappingsList, isDarkMode, currentColorProfile);
94
+ const colors = getMappingColors(mappingsListFromMetadata, isDarkMode, currentColorProfile);
124
95
  return colors;
125
- }, [isDarkMode, mappingsList, currentColorProfile]);
96
+ }, [isDarkMode, mappingsListFromMetadata, currentColorProfile]);
126
97
  const colorByList = {
127
98
  filename: filenameColors,
128
99
  binary: mappingColors,
@@ -31,6 +31,6 @@ export declare const validateFlameChartQuery: (profileSource: MergedProfileSourc
31
31
  isNonDelta: boolean;
32
32
  isDurationTooLong: boolean;
33
33
  };
34
- declare const ProfileFlameGraph: ({ arrow, total, filtered, curPathArrow, setNewCurPathArrow, profileType, loading, error, width, isHalfScreen, metadataMappingFiles, isFlameChart, profileSource, isInSandwichView, isRenderedAsFlamegraph, tooltipId, maxFrameCount, isExpanded, }: ProfileFlameGraphProps) => JSX.Element;
34
+ declare const ProfileFlameGraph: ({ arrow, total, filtered, curPathArrow, setNewCurPathArrow, profileType, loading, error, width, isHalfScreen, metadataMappingFiles, isFlameChart, profileSource, isInSandwichView, isRenderedAsFlamegraph, tooltipId, maxFrameCount, isExpanded, metadataLoading, }: ProfileFlameGraphProps) => JSX.Element;
35
35
  export default ProfileFlameGraph;
36
36
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileFlameGraph/index.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAwE,MAAM,OAAO,CAAC;AAM7F,OAAO,EAAC,eAAe,EAAC,MAAM,eAAe,CAAC;AAO9C,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;AAI1C,OAAO,EAAC,mBAAmB,EAAE,aAAa,EAAC,MAAM,kBAAkB,CAAC;AAMpE,OAAO,EAAC,gBAAgB,EAA0B,MAAM,yBAAyB,CAAC;AAIlF,MAAM,MAAM,aAAa,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;AAEpE,UAAU,sBAAsB;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,aAAa,EAAE,aAAa,CAAC;IAC7B,YAAY,EAAE,gBAAgB,EAAE,GAAG,EAAE,CAAC;IACtC,kBAAkB,EAAE,CAAC,IAAI,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IACvD,OAAO,EAAE,OAAO,CAAC;IACjB,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,OAAO,KAAK,IAAI,CAAC;IACxD,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,YAAY,EAAE,OAAO,CAAC;IACtB,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAUD,eAAO,MAAM,uBAAuB,GAClC,eAAe,mBAAmB,KACjC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,OAAO,CAAC;IAAC,iBAAiB,EAAE,OAAO,CAAA;CAMpE,CAAC;AAEF,QAAA,MAAM,iBAAiB,GAAqC,oPAmBzD,sBAAsB,KAAG,GAAG,CAAC,OAkT/B,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileFlameGraph/index.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAwE,MAAM,OAAO,CAAC;AAM7F,OAAO,EAAC,eAAe,EAAC,MAAM,eAAe,CAAC;AAO9C,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;AAI1C,OAAO,EAAC,mBAAmB,EAAE,aAAa,EAAC,MAAM,kBAAkB,CAAC;AAOpE,OAAO,EAAC,gBAAgB,EAA0B,MAAM,yBAAyB,CAAC;AAIlF,MAAM,MAAM,aAAa,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;AAEpE,UAAU,sBAAsB;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,aAAa,EAAE,aAAa,CAAC;IAC7B,YAAY,EAAE,gBAAgB,EAAE,GAAG,EAAE,CAAC;IACtC,kBAAkB,EAAE,CAAC,IAAI,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IACvD,OAAO,EAAE,OAAO,CAAC;IACjB,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,OAAO,KAAK,IAAI,CAAC;IACxD,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,YAAY,EAAE,OAAO,CAAC;IACtB,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAUD,eAAO,MAAM,uBAAuB,GAClC,eAAe,mBAAmB,KACjC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,OAAO,CAAC;IAAC,iBAAiB,EAAE,OAAO,CAAA;CAMpE,CAAC;AAEF,QAAA,MAAM,iBAAiB,GAAqC,qQAoBzD,sBAAsB,KAAG,GAAG,CAAC,OA0T/B,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
@@ -20,9 +20,10 @@ import { testId } from '@parca/test-utils';
20
20
  import { capitalizeOnlyFirstLetter, divide } from '@parca/utilities';
21
21
  import DiffLegend from '../ProfileView/components/DiffLegend';
22
22
  import { useProfileViewContext } from '../ProfileView/context/ProfileViewContext';
23
+ import { useProfileMetadata } from '../ProfileView/hooks/useProfileMetadata';
24
+ import { useVisualizationState } from '../ProfileView/hooks/useVisualizationState';
23
25
  import { TimelineGuide } from '../TimelineGuide';
24
26
  import { FlameGraphArrow } from './FlameGraphArrow';
25
- import useMappingList from './FlameGraphArrow/useMappingList';
26
27
  import { boundsFromProfileSource } from './FlameGraphArrow/utils';
27
28
  const numberFormatter = new Intl.NumberFormat('en-US');
28
29
  const ErrorContent = ({ errorMessage }) => {
@@ -35,11 +36,12 @@ export const validateFlameChartQuery = (profileSource) => {
35
36
  const isDurationTooLong = duration > 60000000000n; // 60 seconds in nanoseconds
36
37
  return { isValid: !isNonDelta && !isDurationTooLong, isNonDelta, isDurationTooLong };
37
38
  };
38
- const ProfileFlameGraph = function ProfileFlameGraphNonMemo({ arrow, total, filtered, curPathArrow, setNewCurPathArrow, profileType, loading, error, width, isHalfScreen, metadataMappingFiles, isFlameChart = false, profileSource, isInSandwichView = false, isRenderedAsFlamegraph = false, tooltipId, maxFrameCount, isExpanded = false, }) {
39
+ const ProfileFlameGraph = function ProfileFlameGraphNonMemo({ arrow, total, filtered, curPathArrow, setNewCurPathArrow, profileType, loading, error, width, isHalfScreen, metadataMappingFiles, isFlameChart = false, profileSource, isInSandwichView = false, isRenderedAsFlamegraph = false, tooltipId, maxFrameCount, isExpanded = false, metadataLoading = false, }) {
39
40
  const { onError, authenticationErrorMessage, isDarkMode, flamechartHelpText } = useParcaContext();
40
41
  const { compareMode } = useProfileViewContext();
41
42
  const [isLoading, setIsLoading] = useState(true);
42
43
  const [flameChartRef, { height: flameChartHeight }] = useMeasure();
44
+ const { colorBy, setColorBy } = useVisualizationState();
43
45
  // Create local state for paths when in sandwich view to avoid URL updates
44
46
  const [localCurPathArrow, setLocalCurPathArrow] = useState([]);
45
47
  const setCurPathArrowWrapper = useCallback((path) => {
@@ -52,8 +54,12 @@ const ProfileFlameGraph = function ProfileFlameGraphNonMemo({ arrow, total, filt
52
54
  }, [isInSandwichView, setNewCurPathArrow]);
53
55
  // Determine which paths to use based on isInSandwichView flag
54
56
  const effectiveCurPathArrow = isInSandwichView ? localCurPathArrow : curPathArrow;
55
- const mappingsList = useMappingList(metadataMappingFiles);
56
- const [colorBy, setColorBy] = useURLState('color_by');
57
+ const { mappingsList, filenamesList } = useProfileMetadata({
58
+ flamegraphArrow: arrow,
59
+ metadataMappingFiles,
60
+ metadataLoading,
61
+ colorBy,
62
+ });
57
63
  // By default, we want delta profiles (CPU) to be relatively compared.
58
64
  // For non-delta profiles, like goroutines or memory, we want the profiles to be compared absolutely.
59
65
  const compareAbsoluteDefault = profileType?.delta === false ? 'true' : 'false';
@@ -119,7 +125,7 @@ const ProfileFlameGraph = function ProfileFlameGraphNonMemo({ arrow, total, filt
119
125
  if (total === 0n && !loading)
120
126
  return _jsx("div", { className: "mx-auto text-center", children: "Profile has no samples" });
121
127
  if (arrow !== undefined) {
122
- return (_jsxs("div", { className: "relative", children: [isFlameChart ? (_jsx(TimelineGuide, { bounds: boundsFromProfileSource(profileSource), width: width, height: flameChartHeight ?? 420, margin: 0, ticks: 12, timeUnit: "nanoseconds" })) : null, _jsx("div", { ref: flameChartRef, children: _jsx(FlameGraphArrow, { width: width, arrow: arrow, total: total, filtered: filtered, curPath: effectiveCurPathArrow, setCurPath: setCurPathArrowWrapper, profileType: profileType, isHalfScreen: isHalfScreen, mappingsListFromMetadata: mappingsList, compareAbsolute: isCompareAbsolute, isFlameChart: isFlameChart, profileSource: profileSource, isRenderedAsFlamegraph: isRenderedAsFlamegraph, isInSandwichView: isInSandwichView, tooltipId: tooltipId, maxFrameCount: maxFrameCount, isExpanded: isExpanded }) })] }));
128
+ return (_jsxs("div", { className: "relative", children: [isFlameChart ? (_jsx(TimelineGuide, { bounds: boundsFromProfileSource(profileSource), width: width, height: flameChartHeight ?? 420, margin: 0, ticks: 12, timeUnit: "nanoseconds" })) : null, _jsx("div", { ref: flameChartRef, children: _jsx(FlameGraphArrow, { width: width, arrow: arrow, total: total, filtered: filtered, curPath: effectiveCurPathArrow, setCurPath: setCurPathArrowWrapper, profileType: profileType, isHalfScreen: isHalfScreen, mappingsListFromMetadata: mappingsList, filenamesListFromMetadata: filenamesList, compareAbsolute: isCompareAbsolute, isFlameChart: isFlameChart, profileSource: profileSource, isRenderedAsFlamegraph: isRenderedAsFlamegraph, isInSandwichView: isInSandwichView, tooltipId: tooltipId, maxFrameCount: maxFrameCount, isExpanded: isExpanded, colorBy: colorBy }) })] }));
123
129
  }
124
130
  }, [
125
131
  isLoading,
@@ -131,7 +137,6 @@ const ProfileFlameGraph = function ProfileFlameGraphNonMemo({ arrow, total, filt
131
137
  profileType,
132
138
  isHalfScreen,
133
139
  isDarkMode,
134
- mappingsList,
135
140
  isCompareAbsolute,
136
141
  isFlameChart,
137
142
  profileSource,
@@ -145,6 +150,9 @@ const ProfileFlameGraph = function ProfileFlameGraphNonMemo({ arrow, total, filt
145
150
  tooltipId,
146
151
  maxFrameCount,
147
152
  isExpanded,
153
+ mappingsList,
154
+ filenamesList,
155
+ colorBy,
148
156
  ]);
149
157
  useEffect(() => {
150
158
  if (isTrimmed) {
@@ -15,8 +15,6 @@ interface GetDashboardItemProps {
15
15
  profileSource: ProfileSource;
16
16
  total: bigint;
17
17
  filtered: bigint;
18
- curPath: string[];
19
- setNewCurPath: (path: string[]) => void;
20
18
  curPathArrow: CurrentPathFrame[];
21
19
  setNewCurPathArrow: (path: CurrentPathFrame[]) => void;
22
20
  perf?: {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/ProfileView/components/DashboardItems/index.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAW,wBAAwB,EAAC,MAAM,OAAO,CAAC;AAEzD,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAIjD,OAAO,EAAC,gBAAgB,EAAC,MAAM,kDAAkD,CAAC;AAClF,OAAO,EAAC,aAAa,EAAC,MAAM,wBAAwB,CAAC;AAIrD,OAAO,KAAK,EACV,cAAc,EACd,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,iBAAiB,EAClB,MAAM,2BAA2B,CAAC;AAEnC,UAAU,qBAAqB;IAC7B,IAAI,EAAE,iBAAiB,CAAC;IACxB,YAAY,EAAE,OAAO,CAAC;IACtB,UAAU,EAAE,OAAO,GAAG,SAAS,CAAC;IAChC,cAAc,EAAE,cAAc,CAAC;IAC/B,cAAc,EAAE,cAAc,CAAC;IAC/B,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,YAAY,EAAE,YAAY,CAAC;IAC3B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,aAAa,EAAE,aAAa,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACxC,YAAY,EAAE,gBAAgB,EAAE,CAAC;IACjC,kBAAkB,EAAE,CAAC,IAAI,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IACvD,IAAI,CAAC,EAAE;QACL,QAAQ,CAAC,EAAE,wBAAwB,CAAC;KACrC,CAAC;IACF,WAAW,CAAC,EAAE,kBAAkB,CAAC;CAClC;AAED,eAAO,MAAM,gBAAgB,GAAI,qLAe9B,qBAAqB,KAAG,GAAG,CAAC,OA+F9B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/ProfileView/components/DashboardItems/index.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAW,wBAAwB,EAAC,MAAM,OAAO,CAAC;AAEzD,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAIjD,OAAO,EAAC,gBAAgB,EAAC,MAAM,kDAAkD,CAAC;AAClF,OAAO,EAAC,aAAa,EAAC,MAAM,wBAAwB,CAAC;AAIrD,OAAO,KAAK,EACV,cAAc,EACd,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,iBAAiB,EAClB,MAAM,2BAA2B,CAAC;AAEnC,UAAU,qBAAqB;IAC7B,IAAI,EAAE,iBAAiB,CAAC;IACxB,YAAY,EAAE,OAAO,CAAC;IACtB,UAAU,EAAE,OAAO,GAAG,SAAS,CAAC;IAChC,cAAc,EAAE,cAAc,CAAC;IAC/B,cAAc,EAAE,cAAc,CAAC;IAC/B,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,YAAY,EAAE,YAAY,CAAC;IAC3B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,aAAa,EAAE,aAAa,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,gBAAgB,EAAE,CAAC;IACjC,kBAAkB,EAAE,CAAC,IAAI,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IACvD,IAAI,CAAC,EAAE;QACL,QAAQ,CAAC,EAAE,wBAAwB,CAAC;KACrC,CAAC;IACF,WAAW,CAAC,EAAE,kBAAkB,CAAC;CAClC;AAED,eAAO,MAAM,gBAAgB,GAAI,qLAe9B,qBAAqB,KAAG,GAAG,CAAC,OA+F9B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"useProfileFilters.d.ts","sourceRoot":"","sources":["../../../../src/ProfileView/components/ProfileFilters/useProfileFilters.ts"],"names":[],"mappings":"AAeA,OAAO,EAAC,KAAK,MAAM,EAA6C,MAAM,eAAe,CAAC;AAKtF,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,GAAG,MAAM,CAAC;IAClC,KAAK,CAAC,EAAE,eAAe,GAAG,QAAQ,GAAG,aAAa,GAAG,UAAU,GAAG,SAAS,GAAG,aAAa,CAAC;IAC5F,SAAS,CAAC,EAAE,OAAO,GAAG,WAAW,GAAG,UAAU,GAAG,cAAc,CAAC;IAChE,KAAK,EAAE,MAAM,CAAC;CACf;AAqBD,eAAO,MAAM,uBAAuB,GAAI,cAAc,MAAM,EAAE,KAAG,aAAa,EA+E7E,CAAC;AAGF,eAAO,MAAM,qBAAqB,GAAI,gBAAgB,aAAa,EAAE,KAAG,MAAM,EAmF7E,CAAC;AAEF,eAAO,MAAM,iBAAiB,QAAO;IACnC,YAAY,EAAE,aAAa,EAAE,CAAC;IAC9B,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,aAAa,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,mBAAmB,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,KAAK,IAAI,CAAC;IACpE,YAAY,EAAE,MAAM,IAAI,CAAC;CAsL1B,CAAC"}
1
+ {"version":3,"file":"useProfileFilters.d.ts","sourceRoot":"","sources":["../../../../src/ProfileView/components/ProfileFilters/useProfileFilters.ts"],"names":[],"mappings":"AAeA,OAAO,EAAC,KAAK,MAAM,EAA6C,MAAM,eAAe,CAAC;AAMtF,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,GAAG,MAAM,CAAC;IAClC,KAAK,CAAC,EAAE,eAAe,GAAG,QAAQ,GAAG,aAAa,GAAG,UAAU,GAAG,SAAS,GAAG,aAAa,CAAC;IAC5F,SAAS,CAAC,EAAE,OAAO,GAAG,WAAW,GAAG,UAAU,GAAG,cAAc,CAAC;IAChE,KAAK,EAAE,MAAM,CAAC;CACf;AAqBD,eAAO,MAAM,uBAAuB,GAAI,cAAc,MAAM,EAAE,KAAG,aAAa,EA+E7E,CAAC;AAGF,eAAO,MAAM,qBAAqB,GAAI,gBAAgB,aAAa,EAAE,KAAG,MAAM,EAmF7E,CAAC;AAEF,eAAO,MAAM,iBAAiB,QAAO;IACnC,YAAY,EAAE,aAAa,EAAE,CAAC;IAC9B,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,aAAa,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,mBAAmB,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,KAAK,IAAI,CAAC;IACpE,YAAY,EAAE,MAAM,IAAI,CAAC;CA2L1B,CAAC"}
@@ -11,6 +11,7 @@
11
11
  // See the License for the specific language governing permissions and
12
12
  // limitations under the License.
13
13
  import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
14
+ import { useResetFlameGraphState } from '../../hooks/useResetFlameGraphState';
14
15
  import { getPresetByKey, isPresetKey } from './filterPresets';
15
16
  import { useProfileFiltersUrlState } from './useProfileFiltersUrlState';
16
17
  const createStringCondition = (matchType, value) => ({
@@ -182,6 +183,7 @@ export const convertToProtoFilters = (profileFilters) => {
182
183
  };
183
184
  export const useProfileFilters = () => {
184
185
  const { appliedFilters, setAppliedFilters } = useProfileFiltersUrlState();
186
+ const resetFlameGraphState = useResetFlameGraphState();
185
187
  const [localFilters, setLocalFilters] = useState(appliedFilters ?? []);
186
188
  const lastAppliedFiltersRef = useRef([]);
187
189
  const localFiltersRef = useRef(localFilters);
@@ -259,9 +261,10 @@ export const useProfileFilters = () => {
259
261
  // Auto-apply the filter since it has a value
260
262
  const filtersToApply = [...(appliedFilters ?? []), newFilter];
261
263
  setAppliedFilters(filtersToApply);
264
+ resetFlameGraphState();
262
265
  },
263
266
  // eslint-disable-next-line react-hooks/exhaustive-deps
264
- [setAppliedFilters]);
267
+ [setAppliedFilters, resetFlameGraphState]);
265
268
  const removeExcludeBinary = useCallback((binaryName) => {
266
269
  // Search for the exclude filter (not_contains) for this binary
267
270
  const filterToRemove = (appliedFilters ?? []).find(f => f.type === 'frame' &&
@@ -272,10 +275,11 @@ export const useProfileFilters = () => {
272
275
  // Remove the filter from applied filters
273
276
  const updatedAppliedFilters = (appliedFilters ?? []).filter(f => f.id !== filterToRemove.id);
274
277
  setAppliedFilters(updatedAppliedFilters);
278
+ resetFlameGraphState();
275
279
  // Also remove from local filters
276
280
  setLocalFilters(localFiltersRef.current.filter(f => f.id !== filterToRemove.id));
277
281
  }
278
- }, [appliedFilters, setAppliedFilters]);
282
+ }, [appliedFilters, setAppliedFilters, resetFlameGraphState]);
279
283
  const removeFilter = useCallback((id) => {
280
284
  setLocalFilters(localFiltersRef.current.filter(f => f.id !== id));
281
285
  }, []);
@@ -285,7 +289,8 @@ export const useProfileFilters = () => {
285
289
  const resetFilters = useCallback(() => {
286
290
  setLocalFilters([]);
287
291
  setAppliedFilters([]);
288
- }, [setAppliedFilters]);
292
+ resetFlameGraphState();
293
+ }, [setAppliedFilters, resetFlameGraphState]);
289
294
  const onApplyFilters = useCallback(() => {
290
295
  const validFilters = localFiltersRef.current.filter(f => {
291
296
  // For preset filters, only need type and value
@@ -300,7 +305,8 @@ export const useProfileFilters = () => {
300
305
  id: `filter-${Date.now()}-${index}`,
301
306
  }));
302
307
  setAppliedFilters(filtersToApply);
303
- }, [setAppliedFilters]);
308
+ resetFlameGraphState();
309
+ }, [setAppliedFilters, resetFlameGraphState]);
304
310
  const protoFilters = useMemo(() => {
305
311
  return convertToProtoFilters(appliedFilters ?? []);
306
312
  }, [appliedFilters]);
@@ -0,0 +1,2 @@
1
+ export declare const useResetFlameGraphState: () => (() => void);
2
+ //# sourceMappingURL=useResetFlameGraphState.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useResetFlameGraphState.d.ts","sourceRoot":"","sources":["../../../src/ProfileView/hooks/useResetFlameGraphState.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,uBAAuB,QAAO,CAAC,MAAM,IAAI,CAWrD,CAAC"}
@@ -11,7 +11,7 @@
11
11
  // See the License for the specific language governing permissions and
12
12
  // limitations under the License.
13
13
  import { useURLState } from '@parca/components';
14
- export const useResetStateOnNewSearch = () => {
14
+ export const useResetFlameGraphState = () => {
15
15
  const [val, setCurPath] = useURLState('cur_path');
16
16
  return () => {
17
17
  setTimeout(() => {
@@ -1,7 +1,5 @@
1
1
  import { CurrentPathFrame } from '../../ProfileFlameGraph/FlameGraphArrow/utils';
2
2
  export declare const useVisualizationState: () => {
3
- curPath: string[];
4
- setCurPath: (path: string[]) => void;
5
3
  curPathArrow: CurrentPathFrame[];
6
4
  setCurPathArrow: (path: CurrentPathFrame[]) => void;
7
5
  colorStackLegend: string | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"useVisualizationState.d.ts","sourceRoot":"","sources":["../../../src/ProfileView/hooks/useVisualizationState.ts"],"names":[],"mappings":"AAwBA,OAAO,EAAC,gBAAgB,EAAC,MAAM,+CAA+C,CAAC;AAE/E,eAAO,MAAM,qBAAqB,QAAO;IACvC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACrC,YAAY,EAAE,gBAAgB,EAAE,CAAC;IACjC,eAAe,EAAE,CAAC,IAAI,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IACpD,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACrC,aAAa,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,gBAAgB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IAC7C,oBAAoB,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,uBAAuB,EAAE,CAAC,oBAAoB,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IAC5E,yBAAyB,EAAE,MAAM,IAAI,CAAC;CA0EvC,CAAC"}
1
+ {"version":3,"file":"useVisualizationState.d.ts","sourceRoot":"","sources":["../../../src/ProfileView/hooks/useVisualizationState.ts"],"names":[],"mappings":"AAwBA,OAAO,EAAC,gBAAgB,EAAC,MAAM,+CAA+C,CAAC;AAG/E,eAAO,MAAM,qBAAqB,QAAO;IACvC,YAAY,EAAE,gBAAgB,EAAE,CAAC;IACjC,eAAe,EAAE,CAAC,IAAI,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IACpD,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACrC,aAAa,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,gBAAgB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IAC7C,oBAAoB,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,uBAAuB,EAAE,CAAC,oBAAoB,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IAC5E,yBAAyB,EAAE,MAAM,IAAI,CAAC;CA0EvC,CAAC"}
@@ -10,11 +10,11 @@
10
10
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
11
  // See the License for the specific language governing permissions and
12
12
  // limitations under the License.
13
- import { useCallback, useMemo, useState } from 'react';
13
+ import { useCallback, useMemo } from 'react';
14
14
  import { JSONParser, JSONSerializer, useURLState, useURLStateCustom } from '@parca/components';
15
15
  import { FIELD_FUNCTION_FILE_NAME, FIELD_FUNCTION_NAME, FIELD_LABELS, FIELD_LOCATION_ADDRESS, FIELD_MAPPING_FILE, } from '../../ProfileFlameGraph/FlameGraphArrow';
16
+ import { useResetFlameGraphState } from './useResetFlameGraphState';
16
17
  export const useVisualizationState = () => {
17
- const [curPath, setCurPath] = useState([]);
18
18
  const [curPathArrow, setCurPathArrow] = useURLStateCustom('cur_path', {
19
19
  parse: (JSONParser),
20
20
  stringify: JSONSerializer,
@@ -27,6 +27,7 @@ export const useVisualizationState = () => {
27
27
  alwaysReturnArray: true,
28
28
  });
29
29
  const [sandwichFunctionName, setSandwichFunctionName] = useURLState('sandwich_function_name');
30
+ const resetFlameGraphState = useResetFlameGraphState();
30
31
  const levelsOfProfiling = useMemo(() => [
31
32
  FIELD_FUNCTION_NAME,
32
33
  FIELD_FUNCTION_FILE_NAME,
@@ -44,7 +45,8 @@ export const useVisualizationState = () => {
44
45
  const filteredGroupBy = groupBy.filter(item => !levelsOfProfiling.includes(item));
45
46
  setGroupBy([...filteredGroupBy, key]); // add
46
47
  }
47
- }, [groupBy, setGroupBy, levelsOfProfiling]);
48
+ resetFlameGraphState();
49
+ }, [groupBy, setGroupBy, levelsOfProfiling, resetFlameGraphState]);
48
50
  const setGroupByLabels = useCallback((labels) => {
49
51
  setGroupBy(groupBy.filter(l => !l.startsWith(`${FIELD_LABELS}.`)).concat(labels));
50
52
  }, [groupBy, setGroupBy]);
@@ -52,8 +54,6 @@ export const useVisualizationState = () => {
52
54
  setSandwichFunctionName(undefined);
53
55
  }, [setSandwichFunctionName]);
54
56
  return {
55
- curPath,
56
- setCurPath,
57
57
  curPathArrow,
58
58
  setCurPathArrow,
59
59
  colorStackLegend,
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileView/index.tsx"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAAC,gBAAgB,EAAoB,MAAM,uBAAuB,CAAC;AAE/E,eAAO,MAAM,WAAW,GAAI,iMAczB,gBAAgB,KAAG,GAAG,CAAC,OA+HzB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileView/index.tsx"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAAC,gBAAgB,EAAoB,MAAM,uBAAuB,CAAC;AAE/E,eAAO,MAAM,WAAW,GAAI,iMAczB,gBAAgB,KAAG,GAAG,CAAC,OA2HzB,CAAC"}
@@ -26,7 +26,7 @@ import { useVisualizationState } from './hooks/useVisualizationState';
26
26
  export const ProfileView = ({ total, filtered, flamegraphData, flamechartData, topTableData, sourceData, profileSource, queryClient, onDownloadPProf, pprofDownloading, compare, showVisualizationSelector, sandwichData, }) => {
27
27
  const { timezone, perf, profileViewExternalMainActions, preferencesModal, profileViewExternalSubActions, } = useParcaContext();
28
28
  const { ref, dimensions } = useContainerDimensions();
29
- const { curPath, setCurPath, curPathArrow, setCurPathArrow, colorStackLegend, colorBy, groupBy, toggleGroupBy, setGroupByLabels, sandwichFunctionName, resetSandwichFunctionName, } = useVisualizationState();
29
+ const { curPathArrow, setCurPathArrow, colorStackLegend, colorBy, groupBy, toggleGroupBy, setGroupByLabels, sandwichFunctionName, resetSandwichFunctionName, } = useVisualizationState();
30
30
  const { colorMappings } = useProfileMetadata({
31
31
  flamegraphArrow: flamegraphData.arrow,
32
32
  metadataMappingFiles: flamegraphData.metadataMappingFiles,
@@ -49,8 +49,6 @@ export const ProfileView = ({ total, filtered, flamegraphData, flamechartData, t
49
49
  profileSource,
50
50
  total,
51
51
  filtered,
52
- curPath,
53
- setNewCurPath: setCurPath,
54
52
  curPathArrow,
55
53
  setNewCurPathArrow: setCurPathArrow,
56
54
  perf,
@@ -39,7 +39,7 @@ export const ProfileViewWithData = ({ queryClient, profileSource, showVisualizat
39
39
  const { protoFilters } = useProfileFilters();
40
40
  useEffect(() => {
41
41
  // If profile type is not delta, remove flamechart from the dashboard items
42
- // and set it to flame if no other items are selected.
42
+ // and set it to flame graph if no other items are selected.
43
43
  if (profileSource == null) {
44
44
  return;
45
45
  }
package/package.json CHANGED
@@ -1,20 +1,20 @@
1
1
  {
2
2
  "name": "@parca/profile",
3
- "version": "0.19.51",
3
+ "version": "0.19.53",
4
4
  "description": "Profile viewing libraries",
5
5
  "dependencies": {
6
6
  "@floating-ui/react": "^0.27.12",
7
7
  "@headlessui/react": "^1.7.19",
8
8
  "@iconify/react": "^4.0.0",
9
- "@parca/client": "0.17.4",
10
- "@parca/components": "0.16.369",
11
- "@parca/dynamicsize": "0.16.66",
12
- "@parca/hooks": "0.0.101",
13
- "@parca/icons": "0.16.73",
14
- "@parca/parser": "0.16.80",
15
- "@parca/store": "0.16.185",
16
- "@parca/test-utils": "0.0.11",
17
- "@parca/utilities": "0.0.108",
9
+ "@parca/client": "0.17.5",
10
+ "@parca/components": "0.16.370",
11
+ "@parca/dynamicsize": "0.16.67",
12
+ "@parca/hooks": "0.0.102",
13
+ "@parca/icons": "0.16.74",
14
+ "@parca/parser": "0.16.81",
15
+ "@parca/store": "0.16.186",
16
+ "@parca/test-utils": "0.0.12",
17
+ "@parca/utilities": "0.0.109",
18
18
  "@popperjs/core": "^2.11.8",
19
19
  "@protobuf-ts/runtime-rpc": "^2.5.0",
20
20
  "@storybook/preview-api": "^8.4.3",
@@ -79,5 +79,5 @@
79
79
  "access": "public",
80
80
  "registry": "https://registry.npmjs.org/"
81
81
  },
82
- "gitHead": "604f94cd9e0fa0f52628a3e46132a5218a12fd3a"
82
+ "gitHead": "364f74584252524568010bb27636fdb87fe7aee7"
83
83
  }
@@ -23,7 +23,7 @@ import {capitalizeOnlyFirstLetter, safeDecode, type NavigateFunction} from '@par
23
23
 
24
24
  import {ProfileSelection, ProfileSelectionFromParams, SuffixParams} from '..';
25
25
  import {QuerySelection, useProfileTypes} from '../ProfileSelector';
26
- import {useResetStateOnNewSearch} from '../ProfileView/hooks/useResetStateOnNewSearch';
26
+ import {useResetFlameGraphState} from '../ProfileView/hooks/useResetFlameGraphState';
27
27
  import {useResetStateOnProfileTypeChange} from '../ProfileView/hooks/useResetStateOnProfileTypeChange';
28
28
  import {sumByToParam, useSumByFromParams} from '../useSumBy';
29
29
  import ProfileExplorerCompare from './ProfileExplorerCompare';
@@ -162,7 +162,7 @@ const ProfileExplorerApp = ({
162
162
  const [profileB, setProfileB] = useState<ProfileSelection | null>(null);
163
163
 
164
164
  const resetStateOnProfileTypeChange = useResetStateOnProfileTypeChange();
165
- const resetStateOnNewSearch = useResetStateOnNewSearch();
165
+ const resetFlameGraphState = useResetFlameGraphState();
166
166
 
167
167
  const sumByA = useSumByFromParams(sum_by_a);
168
168
  const sumByB = useSumByFromParams(sum_by_b);
@@ -250,7 +250,7 @@ const ProfileExplorerApp = ({
250
250
  resetStateOnProfileTypeChange();
251
251
  } else {
252
252
  // Reset the state when a new search is performed.
253
- resetStateOnNewSearch();
253
+ resetFlameGraphState();
254
254
  }
255
255
  }
256
256
 
@@ -130,8 +130,6 @@ export const FlameNode = React.memo(
130
130
  const colorAttribute =
131
131
  colorBy === 'filename' ? filename : colorBy === 'binary' ? mappingFile : null;
132
132
 
133
- const colorsMap = colors;
134
-
135
133
  const hoveringName =
136
134
  hoveringRow !== undefined ? arrowToString(functionNameColumn?.get(hoveringRow)) : '';
137
135
  const shouldBeHighlighted =
@@ -142,7 +140,7 @@ export const FlameNode = React.memo(
142
140
  compareMode,
143
141
  cumulative,
144
142
  diff,
145
- colorsMap,
143
+ colorsMap: colors,
146
144
  colorAttribute,
147
145
  });
148
146
 
@@ -296,7 +294,9 @@ export const FlameNode = React.memo(
296
294
  prevProps.hoveringRow === nextProps.hoveringRow &&
297
295
  prevProps.totalWidth === nextProps.totalWidth &&
298
296
  prevProps.height === nextProps.height &&
299
- prevProps.effectiveDepth === nextProps.effectiveDepth
297
+ prevProps.effectiveDepth === nextProps.effectiveDepth &&
298
+ prevProps.colorBy === nextProps.colorBy &&
299
+ prevProps.colors === nextProps.colors
300
300
  );
301
301
  }
302
302
  );
@@ -21,15 +21,15 @@ import React, {
21
21
  useState,
22
22
  } from 'react';
23
23
 
24
- import {Dictionary, Table, Vector, tableFromIPC} from 'apache-arrow';
24
+ import {Table, tableFromIPC} from 'apache-arrow';
25
25
  import {useContextMenu} from 'react-contexify';
26
26
 
27
27
  import {FlamegraphArrow} from '@parca/client';
28
- import {useParcaContext, useURLState} from '@parca/components';
28
+ import {useParcaContext} from '@parca/components';
29
29
  import {USER_PREFERENCES, useCurrentColorProfile, useUserPreference} from '@parca/hooks';
30
30
  import {ProfileType} from '@parca/parser';
31
31
  import {getColorForFeature, selectDarkMode, useAppSelector} from '@parca/store';
32
- import {getLastItem, type ColorConfig} from '@parca/utilities';
32
+ import {type ColorConfig} from '@parca/utilities';
33
33
 
34
34
  import {ProfileSource} from '../../ProfileSource';
35
35
  import {useProfileFilters} from '../../ProfileView/components/ProfileFilters/useProfileFilters';
@@ -38,12 +38,10 @@ import ContextMenuWrapper, {ContextMenuWrapperRef} from './ContextMenuWrapper';
38
38
  import {FlameNode, RowHeight, colorByColors} from './FlameGraphNodes';
39
39
  import {MemoizedTooltip} from './MemoizedTooltip';
40
40
  import {TooltipProvider} from './TooltipContext';
41
- import {useFilenamesList} from './useMappingList';
42
41
  import {useScrollViewport} from './useScrollViewport';
43
42
  import {useVisibleNodes} from './useVisibleNodes';
44
43
  import {
45
44
  CurrentPathFrame,
46
- arrowToString,
47
45
  extractFeature,
48
46
  extractFilenameFeature,
49
47
  getCurrentPathFrameData,
@@ -84,6 +82,8 @@ interface FlameGraphArrowProps {
84
82
  setCurPath: (path: CurrentPathFrame[]) => void;
85
83
  isHalfScreen: boolean;
86
84
  mappingsListFromMetadata: string[];
85
+ filenamesListFromMetadata: string[];
86
+ colorBy: string;
87
87
  compareAbsolute: boolean;
88
88
  isFlameChart?: boolean;
89
89
  isRenderedAsFlamegraph?: boolean;
@@ -139,6 +139,9 @@ export const FlameGraphArrow = memo(function FlameGraphArrow({
139
139
  tooltipId = 'default',
140
140
  maxFrameCount,
141
141
  isExpanded = false,
142
+ mappingsListFromMetadata,
143
+ filenamesListFromMetadata,
144
+ colorBy,
142
145
  }: FlameGraphArrowProps): React.JSX.Element {
143
146
  const [highlightSimilarStacksPreference] = useUserPreference<boolean>(
144
147
  USER_PREFERENCES.HIGHLIGHT_SIMILAR_STACKS.key
@@ -169,49 +172,17 @@ export const FlameGraphArrow = memo(function FlameGraphArrow({
169
172
  const currentColorProfile = useCurrentColorProfile();
170
173
  const colorForSimilarNodes = currentColorProfile.colorForSimilarNodes;
171
174
 
172
- const [colorBy, _] = useURLState('color_by');
173
- const colorByValue = colorBy === undefined || colorBy === '' ? 'binary' : (colorBy as string);
174
-
175
- const filenamesList = useFilenamesList(table);
176
-
177
- const mappingsList = useMemo(() => {
178
- // Read the mappings from the dictionary that contains all mapping strings.
179
- // This is great, as might only have a dozen or so mappings,
180
- // and don't need to read through all the rows (potentially thousands).
181
- const mappingsDict: Vector<Dictionary> | null = table.getChild(FIELD_MAPPING_FILE);
182
- const mappings =
183
- mappingsDict?.data
184
- .map(mapping => {
185
- if (mapping.dictionary == null) {
186
- return [];
187
- }
188
- const len = mapping.dictionary.length;
189
- const entries: string[] = [];
190
- for (let i = 0; i < len; i++) {
191
- const fn = arrowToString(mapping.dictionary.get(i));
192
- entries.push(getLastItem(fn) ?? '');
193
- }
194
- return entries;
195
- })
196
- .flat() ?? [];
197
-
198
- // We add a EVERYTHING ELSE mapping to the list.
199
- mappings.push('');
200
-
201
- // We sort the mappings alphabetically to make sure that the order is always the same.
202
- mappings.sort((a, b) => a.localeCompare(b));
203
- return mappings;
204
- }, [table]);
175
+ const colorByValue = colorBy === undefined || colorBy === '' ? 'binary' : colorBy;
205
176
 
206
177
  const filenameColors = useMemo(() => {
207
- const colors = getFilenameColors(filenamesList, isDarkMode, currentColorProfile);
178
+ const colors = getFilenameColors(filenamesListFromMetadata, isDarkMode, currentColorProfile);
208
179
  return colors;
209
- }, [isDarkMode, filenamesList, currentColorProfile]);
180
+ }, [isDarkMode, filenamesListFromMetadata, currentColorProfile]);
210
181
 
211
182
  const mappingColors = useMemo(() => {
212
- const colors = getMappingColors(mappingsList, isDarkMode, currentColorProfile);
183
+ const colors = getMappingColors(mappingsListFromMetadata, isDarkMode, currentColorProfile);
213
184
  return colors;
214
- }, [isDarkMode, mappingsList, currentColorProfile]);
185
+ }, [isDarkMode, mappingsListFromMetadata, currentColorProfile]);
215
186
 
216
187
  const colorByList = {
217
188
  filename: filenameColors,
@@ -31,9 +31,10 @@ import {capitalizeOnlyFirstLetter, divide} from '@parca/utilities';
31
31
  import {MergedProfileSource, ProfileSource} from '../ProfileSource';
32
32
  import DiffLegend from '../ProfileView/components/DiffLegend';
33
33
  import {useProfileViewContext} from '../ProfileView/context/ProfileViewContext';
34
+ import {useProfileMetadata} from '../ProfileView/hooks/useProfileMetadata';
35
+ import {useVisualizationState} from '../ProfileView/hooks/useVisualizationState';
34
36
  import {TimelineGuide} from '../TimelineGuide';
35
37
  import {FlameGraphArrow} from './FlameGraphArrow';
36
- import useMappingList from './FlameGraphArrow/useMappingList';
37
38
  import {CurrentPathFrame, boundsFromProfileSource} from './FlameGraphArrow/utils';
38
39
 
39
40
  const numberFormatter = new Intl.NumberFormat('en-US');
@@ -100,11 +101,13 @@ const ProfileFlameGraph = function ProfileFlameGraphNonMemo({
100
101
  tooltipId,
101
102
  maxFrameCount,
102
103
  isExpanded = false,
104
+ metadataLoading = false,
103
105
  }: ProfileFlameGraphProps): JSX.Element {
104
106
  const {onError, authenticationErrorMessage, isDarkMode, flamechartHelpText} = useParcaContext();
105
107
  const {compareMode} = useProfileViewContext();
106
108
  const [isLoading, setIsLoading] = useState<boolean>(true);
107
109
  const [flameChartRef, {height: flameChartHeight}] = useMeasure();
110
+ const {colorBy, setColorBy} = useVisualizationState();
108
111
 
109
112
  // Create local state for paths when in sandwich view to avoid URL updates
110
113
  const [localCurPathArrow, setLocalCurPathArrow] = useState<CurrentPathFrame[]>([]);
@@ -123,9 +126,12 @@ const ProfileFlameGraph = function ProfileFlameGraphNonMemo({
123
126
  // Determine which paths to use based on isInSandwichView flag
124
127
  const effectiveCurPathArrow = isInSandwichView ? localCurPathArrow : curPathArrow;
125
128
 
126
- const mappingsList = useMappingList(metadataMappingFiles);
127
-
128
- const [colorBy, setColorBy] = useURLState('color_by');
129
+ const {mappingsList, filenamesList} = useProfileMetadata({
130
+ flamegraphArrow: arrow,
131
+ metadataMappingFiles,
132
+ metadataLoading,
133
+ colorBy,
134
+ });
129
135
 
130
136
  // By default, we want delta profiles (CPU) to be relatively compared.
131
137
  // For non-delta profiles, like goroutines or memory, we want the profiles to be compared absolutely.
@@ -279,6 +285,7 @@ const ProfileFlameGraph = function ProfileFlameGraphNonMemo({
279
285
  profileType={profileType}
280
286
  isHalfScreen={isHalfScreen}
281
287
  mappingsListFromMetadata={mappingsList}
288
+ filenamesListFromMetadata={filenamesList}
282
289
  compareAbsolute={isCompareAbsolute}
283
290
  isFlameChart={isFlameChart}
284
291
  profileSource={profileSource}
@@ -287,6 +294,7 @@ const ProfileFlameGraph = function ProfileFlameGraphNonMemo({
287
294
  tooltipId={tooltipId}
288
295
  maxFrameCount={maxFrameCount}
289
296
  isExpanded={isExpanded}
297
+ colorBy={colorBy}
290
298
  />
291
299
  </div>
292
300
  </div>
@@ -302,7 +310,6 @@ const ProfileFlameGraph = function ProfileFlameGraphNonMemo({
302
310
  profileType,
303
311
  isHalfScreen,
304
312
  isDarkMode,
305
- mappingsList,
306
313
  isCompareAbsolute,
307
314
  isFlameChart,
308
315
  profileSource,
@@ -316,6 +323,9 @@ const ProfileFlameGraph = function ProfileFlameGraphNonMemo({
316
323
  tooltipId,
317
324
  maxFrameCount,
318
325
  isExpanded,
326
+ mappingsList,
327
+ filenamesList,
328
+ colorBy,
319
329
  ]);
320
330
 
321
331
  useEffect(() => {
@@ -42,8 +42,6 @@ interface GetDashboardItemProps {
42
42
  profileSource: ProfileSource;
43
43
  total: bigint;
44
44
  filtered: bigint;
45
- curPath: string[];
46
- setNewCurPath: (path: string[]) => void;
47
45
  curPathArrow: CurrentPathFrame[];
48
46
  setNewCurPathArrow: (path: CurrentPathFrame[]) => void;
49
47
  perf?: {
@@ -15,6 +15,7 @@ import {useCallback, useEffect, useMemo, useRef, useState} from 'react';
15
15
 
16
16
  import {type Filter, type NumberCondition, type StringCondition} from '@parca/client';
17
17
 
18
+ import {useResetFlameGraphState} from '../../hooks/useResetFlameGraphState';
18
19
  import {getPresetByKey, isPresetKey} from './filterPresets';
19
20
  import {useProfileFiltersUrlState} from './useProfileFiltersUrlState';
20
21
 
@@ -226,6 +227,7 @@ export const useProfileFilters = (): {
226
227
  resetFilters: () => void;
227
228
  } => {
228
229
  const {appliedFilters, setAppliedFilters} = useProfileFiltersUrlState();
230
+ const resetFlameGraphState = useResetFlameGraphState();
229
231
 
230
232
  const [localFilters, setLocalFilters] = useState<ProfileFilter[]>(appliedFilters ?? []);
231
233
 
@@ -327,9 +329,10 @@ export const useProfileFilters = (): {
327
329
  // Auto-apply the filter since it has a value
328
330
  const filtersToApply = [...(appliedFilters ?? []), newFilter];
329
331
  setAppliedFilters(filtersToApply);
332
+ resetFlameGraphState();
330
333
  },
331
334
  // eslint-disable-next-line react-hooks/exhaustive-deps
332
- [setAppliedFilters]
335
+ [setAppliedFilters, resetFlameGraphState]
333
336
  );
334
337
 
335
338
  const removeExcludeBinary = useCallback(
@@ -349,12 +352,13 @@ export const useProfileFilters = (): {
349
352
  f => f.id !== filterToRemove.id
350
353
  );
351
354
  setAppliedFilters(updatedAppliedFilters);
355
+ resetFlameGraphState();
352
356
 
353
357
  // Also remove from local filters
354
358
  setLocalFilters(localFiltersRef.current.filter(f => f.id !== filterToRemove.id));
355
359
  }
356
360
  },
357
- [appliedFilters, setAppliedFilters]
361
+ [appliedFilters, setAppliedFilters, resetFlameGraphState]
358
362
  );
359
363
 
360
364
  const removeFilter = useCallback((id: string) => {
@@ -368,7 +372,8 @@ export const useProfileFilters = (): {
368
372
  const resetFilters = useCallback(() => {
369
373
  setLocalFilters([]);
370
374
  setAppliedFilters([]);
371
- }, [setAppliedFilters]);
375
+ resetFlameGraphState();
376
+ }, [setAppliedFilters, resetFlameGraphState]);
372
377
 
373
378
  const onApplyFilters = useCallback((): void => {
374
379
  const validFilters = localFiltersRef.current.filter(f => {
@@ -386,7 +391,8 @@ export const useProfileFilters = (): {
386
391
  }));
387
392
 
388
393
  setAppliedFilters(filtersToApply);
389
- }, [setAppliedFilters]);
394
+ resetFlameGraphState();
395
+ }, [setAppliedFilters, resetFlameGraphState]);
390
396
 
391
397
  const protoFilters = useMemo(() => {
392
398
  return convertToProtoFilters(appliedFilters ?? []);
@@ -13,7 +13,7 @@
13
13
 
14
14
  import {useURLState} from '@parca/components';
15
15
 
16
- export const useResetStateOnNewSearch = (): (() => void) => {
16
+ export const useResetFlameGraphState = (): (() => void) => {
17
17
  const [val, setCurPath] = useURLState('cur_path');
18
18
 
19
19
  return () => {
@@ -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 {useCallback, useMemo, useState} from 'react';
14
+ import {useCallback, useMemo} from 'react';
15
15
 
16
16
  import {JSONParser, JSONSerializer, useURLState, useURLStateCustom} from '@parca/components';
17
17
 
@@ -23,10 +23,9 @@ import {
23
23
  FIELD_MAPPING_FILE,
24
24
  } from '../../ProfileFlameGraph/FlameGraphArrow';
25
25
  import {CurrentPathFrame} from '../../ProfileFlameGraph/FlameGraphArrow/utils';
26
+ import {useResetFlameGraphState} from './useResetFlameGraphState';
26
27
 
27
28
  export const useVisualizationState = (): {
28
- curPath: string[];
29
- setCurPath: (path: string[]) => void;
30
29
  curPathArrow: CurrentPathFrame[];
31
30
  setCurPathArrow: (path: CurrentPathFrame[]) => void;
32
31
  colorStackLegend: string | undefined;
@@ -40,7 +39,6 @@ export const useVisualizationState = (): {
40
39
  setSandwichFunctionName: (sandwichFunctionName: string | undefined) => void;
41
40
  resetSandwichFunctionName: () => void;
42
41
  } => {
43
- const [curPath, setCurPath] = useState<string[]>([]);
44
42
  const [curPathArrow, setCurPathArrow] = useURLStateCustom<CurrentPathFrame[]>('cur_path', {
45
43
  parse: JSONParser<CurrentPathFrame[]>,
46
44
  stringify: JSONSerializer,
@@ -55,6 +53,7 @@ export const useVisualizationState = (): {
55
53
  const [sandwichFunctionName, setSandwichFunctionName] = useURLState<string | undefined>(
56
54
  'sandwich_function_name'
57
55
  );
56
+ const resetFlameGraphState = useResetFlameGraphState();
58
57
 
59
58
  const levelsOfProfiling = useMemo(
60
59
  () => [
@@ -81,8 +80,10 @@ export const useVisualizationState = (): {
81
80
  const filteredGroupBy = groupBy.filter(item => !levelsOfProfiling.includes(item));
82
81
  setGroupBy([...filteredGroupBy, key]); // add
83
82
  }
83
+
84
+ resetFlameGraphState();
84
85
  },
85
- [groupBy, setGroupBy, levelsOfProfiling]
86
+ [groupBy, setGroupBy, levelsOfProfiling, resetFlameGraphState]
86
87
  );
87
88
 
88
89
  const setGroupByLabels = useCallback(
@@ -97,8 +98,6 @@ export const useVisualizationState = (): {
97
98
  }, [setSandwichFunctionName]);
98
99
 
99
100
  return {
100
- curPath,
101
- setCurPath,
102
101
  curPathArrow,
103
102
  setCurPathArrow,
104
103
  colorStackLegend,
@@ -56,8 +56,6 @@ export const ProfileView = ({
56
56
  const {ref, dimensions} = useContainerDimensions();
57
57
 
58
58
  const {
59
- curPath,
60
- setCurPath,
61
59
  curPathArrow,
62
60
  setCurPathArrow,
63
61
  colorStackLegend,
@@ -100,8 +98,6 @@ export const ProfileView = ({
100
98
  profileSource,
101
99
  total,
102
100
  filtered,
103
- curPath,
104
- setNewCurPath: setCurPath,
105
101
  curPathArrow,
106
102
  setNewCurPathArrow: setCurPathArrow,
107
103
  perf,
@@ -58,7 +58,7 @@ export const ProfileViewWithData = ({
58
58
 
59
59
  useEffect(() => {
60
60
  // If profile type is not delta, remove flamechart from the dashboard items
61
- // and set it to flame if no other items are selected.
61
+ // and set it to flame graph if no other items are selected.
62
62
  if (profileSource == null) {
63
63
  return;
64
64
  }
@@ -1,2 +0,0 @@
1
- export declare const useResetStateOnNewSearch: () => (() => void);
2
- //# sourceMappingURL=useResetStateOnNewSearch.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useResetStateOnNewSearch.d.ts","sourceRoot":"","sources":["../../../src/ProfileView/hooks/useResetStateOnNewSearch.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,wBAAwB,QAAO,CAAC,MAAM,IAAI,CAWtD,CAAC"}