@parca/profile 0.19.50 → 0.19.52

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.
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.52 (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.51 (2025-09-10)
13
+
14
+ ## 0.24.1 (2025-09-09)
15
+
16
+ **Note:** Version bump only for package @parca/profile
17
+
6
18
  ## [0.19.50](https://github.com/parca-dev/parca/compare/@parca/profile@0.19.49...@parca/profile@0.19.50) (2025-09-08)
7
19
 
8
20
  **Note:** Version bump only for package @parca/profile
@@ -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) {
package/package.json CHANGED
@@ -1,20 +1,20 @@
1
1
  {
2
2
  "name": "@parca/profile",
3
- "version": "0.19.50",
3
+ "version": "0.19.52",
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.3",
10
- "@parca/components": "0.16.368",
11
- "@parca/dynamicsize": "0.16.65",
12
- "@parca/hooks": "0.0.100",
13
- "@parca/icons": "0.16.72",
14
- "@parca/parser": "0.16.79",
15
- "@parca/store": "0.16.184",
16
- "@parca/test-utils": "0.0.10",
17
- "@parca/utilities": "0.0.107",
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": "66b690cf7857609f3726e162a10add19d8288383"
82
+ "gitHead": "df1f4ce1710f808dfc6af0a631b140cd346dfaab"
83
83
  }
@@ -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(() => {