@parca/profile 0.19.95 → 0.19.103

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 (44) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/dist/ProfileFlameGraph/FlameGraphArrow/FlameGraphNodes.d.ts.map +1 -1
  3. package/dist/ProfileFlameGraph/FlameGraphArrow/FlameGraphNodes.js +65 -45
  4. package/dist/ProfileFlameGraph/FlameGraphArrow/index.d.ts.map +1 -1
  5. package/dist/ProfileFlameGraph/FlameGraphArrow/index.js +16 -4
  6. package/dist/ProfileFlameGraph/FlameGraphArrow/useBatchedRendering.d.ts +11 -0
  7. package/dist/ProfileFlameGraph/FlameGraphArrow/useBatchedRendering.d.ts.map +1 -0
  8. package/dist/ProfileFlameGraph/FlameGraphArrow/useBatchedRendering.js +65 -0
  9. package/dist/ProfileFlameGraph/FlameGraphArrow/useScrollViewport.d.ts.map +1 -1
  10. package/dist/ProfileFlameGraph/FlameGraphArrow/useScrollViewport.js +35 -5
  11. package/dist/ProfileFlameGraph/FlameGraphArrow/useVisibleNodes.d.ts.map +1 -1
  12. package/dist/ProfileFlameGraph/FlameGraphArrow/useVisibleNodes.js +29 -3
  13. package/dist/ProfileSelector/MetricsGraphSection.d.ts +1 -1
  14. package/dist/ProfileSelector/MetricsGraphSection.d.ts.map +1 -1
  15. package/dist/ProfileSelector/MetricsGraphSection.js +1 -1
  16. package/dist/ProfileSelector/index.d.ts.map +1 -1
  17. package/dist/ProfileSelector/index.js +1 -2
  18. package/dist/ProfileView/hooks/useResetStateOnProfileTypeChange.d.ts.map +1 -1
  19. package/dist/ProfileView/hooks/useResetStateOnProfileTypeChange.js +8 -0
  20. package/dist/SimpleMatchers/Select.d.ts.map +1 -1
  21. package/dist/SimpleMatchers/Select.js +3 -3
  22. package/dist/hooks/useLabels.d.ts.map +1 -1
  23. package/dist/hooks/useLabels.js +7 -2
  24. package/dist/hooks/useQueryState.d.ts.map +1 -1
  25. package/dist/hooks/useQueryState.js +53 -23
  26. package/dist/hooks/useQueryState.test.js +32 -22
  27. package/dist/styles.css +1 -1
  28. package/dist/useSumBy.d.ts +10 -2
  29. package/dist/useSumBy.d.ts.map +1 -1
  30. package/dist/useSumBy.js +30 -7
  31. package/package.json +15 -10
  32. package/src/ProfileFlameGraph/FlameGraphArrow/FlameGraphNodes.tsx +89 -57
  33. package/src/ProfileFlameGraph/FlameGraphArrow/index.tsx +27 -2
  34. package/src/ProfileFlameGraph/FlameGraphArrow/useBatchedRendering.ts +84 -0
  35. package/src/ProfileFlameGraph/FlameGraphArrow/useScrollViewport.ts +40 -5
  36. package/src/ProfileFlameGraph/FlameGraphArrow/useVisibleNodes.ts +41 -5
  37. package/src/ProfileSelector/MetricsGraphSection.tsx +2 -2
  38. package/src/ProfileSelector/index.tsx +1 -5
  39. package/src/ProfileView/hooks/useResetStateOnProfileTypeChange.ts +8 -0
  40. package/src/SimpleMatchers/Select.tsx +3 -3
  41. package/src/hooks/useLabels.ts +8 -2
  42. package/src/hooks/useQueryState.test.tsx +41 -22
  43. package/src/hooks/useQueryState.ts +72 -31
  44. package/src/useSumBy.ts +58 -4
package/CHANGELOG.md CHANGED
@@ -3,6 +3,38 @@
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.103](https://github.com/parca-dev/parca/compare/@parca/profile@0.19.102...@parca/profile@0.19.103) (2025-12-17)
7
+
8
+ **Note:** Version bump only for package @parca/profile
9
+
10
+ ## [0.19.102](https://github.com/parca-dev/parca/compare/@parca/profile@0.19.101...@parca/profile@0.19.102) (2025-12-15)
11
+
12
+ **Note:** Version bump only for package @parca/profile
13
+
14
+ ## [0.19.101](https://github.com/parca-dev/parca/compare/@parca/profile@0.19.100...@parca/profile@0.19.101) (2025-12-15)
15
+
16
+ **Note:** Version bump only for package @parca/profile
17
+
18
+ ## [0.19.100](https://github.com/parca-dev/parca/compare/@parca/profile@0.19.99...@parca/profile@0.19.100) (2025-12-15)
19
+
20
+ **Note:** Version bump only for package @parca/profile
21
+
22
+ ## [0.19.99](https://github.com/parca-dev/parca/compare/@parca/profile@0.19.98...@parca/profile@0.19.99) (2025-12-12)
23
+
24
+ **Note:** Version bump only for package @parca/profile
25
+
26
+ ## [0.19.98](https://github.com/parca-dev/parca/compare/@parca/profile@0.19.97...@parca/profile@0.19.98) (2025-12-12)
27
+
28
+ **Note:** Version bump only for package @parca/profile
29
+
30
+ ## [0.19.97](https://github.com/parca-dev/parca/compare/@parca/profile@0.19.96...@parca/profile@0.19.97) (2025-12-12)
31
+
32
+ **Note:** Version bump only for package @parca/profile
33
+
34
+ ## [0.19.96](https://github.com/parca-dev/parca/compare/@parca/profile@0.19.95...@parca/profile@0.19.96) (2025-12-12)
35
+
36
+ **Note:** Version bump only for package @parca/profile
37
+
6
38
  ## [0.19.95](https://github.com/parca-dev/parca/compare/@parca/profile@0.19.94...@parca/profile@0.19.95) (2025-12-09)
7
39
 
8
40
  **Note:** Version bump only for package @parca/profile
@@ -1 +1 @@
1
- {"version":3,"file":"FlameGraphNodes.d.ts","sourceRoot":"","sources":["../../../src/ProfileFlameGraph/FlameGraphArrow/FlameGraphNodes.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAgB,MAAM,OAAO,CAAC;AAErC,OAAO,EAAC,KAAK,EAAC,MAAM,cAAc,CAAC;AAKnC,OAAO,yCAAyC,CAAC;AAEjD,OAAO,EAAC,aAAa,EAAC,MAAM,qBAAqB,CAAC;AAelD,eAAO,MAAM,SAAS,KAAK,CAAC;AAE5B,MAAM,WAAW,aAAa;IAC5B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,aAAa,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;IACrB,aAAa,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1D,oBAAoB,EAAE,MAAM,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,YAAY,EAAE,OAAO,CAAC;IACtB,aAAa,EAAE,aAAa,CAAC;IAC7B,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IAGnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;CACnD;AAED,eAAO,MAAM,eAAe;;;CAG3B,CAAC;AACF,eAAO,MAAM,oBAAoB;;;;CAIhC,CAAC;AAEF,eAAO,MAAM,SAAS,4CA6NrB,CAAC"}
1
+ {"version":3,"file":"FlameGraphNodes.d.ts","sourceRoot":"","sources":["../../../src/ProfileFlameGraph/FlameGraphArrow/FlameGraphNodes.tsx"],"names":[],"mappings":"AAaA,OAAO,KAA6B,MAAM,OAAO,CAAC;AAElD,OAAO,EAAC,KAAK,EAAC,MAAM,cAAc,CAAC;AAKnC,OAAO,yCAAyC,CAAC;AAEjD,OAAO,EAAC,aAAa,EAAC,MAAM,qBAAqB,CAAC;AAelD,eAAO,MAAM,SAAS,KAAK,CAAC;AAE5B,MAAM,WAAW,aAAa;IAC5B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,aAAa,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;IACrB,aAAa,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1D,oBAAoB,EAAE,MAAM,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,YAAY,EAAE,OAAO,CAAC;IACtB,aAAa,EAAE,aAAa,CAAC;IAC7B,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IAGnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;CACnD;AAED,eAAO,MAAM,eAAe;;;CAG3B,CAAC;AACF,eAAO,MAAM,oBAAoB;;;;CAIhC,CAAC;AAEF,eAAO,MAAM,SAAS,4CA6PrB,CAAC"}
@@ -11,7 +11,7 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
11
11
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  // See the License for the specific language governing permissions and
13
13
  // limitations under the License.
14
- import React, { useMemo } from 'react';
14
+ import React, { useCallback, useMemo } from 'react';
15
15
  import cx from 'classnames';
16
16
  import { selectBinaries, useAppSelector } from '@parca/store';
17
17
  import 'react-contexify/dist/ReactContexify.css';
@@ -30,28 +30,38 @@ export const fadedFlameRectStyles = {
30
30
  opacity: '0.5',
31
31
  };
32
32
  export const FlameNode = React.memo(function FlameNodeNoMemo({ table, row, colors, colorBy, height, totalWidth, darkMode, compareMode, colorForSimilarNodes, selectedRow, onClick, onContextMenu, hoveringRow, setHoveringRow, isFlameChart, profileSource, isRenderedAsFlamegraph = false, isInSandwichView = false, maxDepth = 0, effectiveDepth, tooltipId = 'default', }) {
33
- // get the columns to read from
34
- const mappingColumn = table.getChild(FIELD_MAPPING_FILE);
35
- const functionNameColumn = table.getChild(FIELD_FUNCTION_NAME);
36
- const cumulativeColumn = table.getChild(FIELD_CUMULATIVE);
37
- const depthColumn = table.getChild(FIELD_DEPTH);
38
- const diffColumn = table.getChild(FIELD_DIFF);
39
- const filenameColumn = table.getChild(FIELD_FUNCTION_FILE_NAME);
40
- const valueOffsetColumn = table.getChild(FIELD_VALUE_OFFSET);
41
- const tsColumn = table.getChild(FIELD_TIMESTAMP);
33
+ // Memoize column references - only changes when table changes
34
+ const columns = useMemo(() => ({
35
+ mapping: table.getChild(FIELD_MAPPING_FILE),
36
+ functionName: table.getChild(FIELD_FUNCTION_NAME),
37
+ cumulative: table.getChild(FIELD_CUMULATIVE),
38
+ depth: table.getChild(FIELD_DEPTH),
39
+ diff: table.getChild(FIELD_DIFF),
40
+ filename: table.getChild(FIELD_FUNCTION_FILE_NAME),
41
+ valueOffset: table.getChild(FIELD_VALUE_OFFSET),
42
+ ts: table.getChild(FIELD_TIMESTAMP),
43
+ }), [table]);
42
44
  // get the actual values from the columns
43
45
  const binaries = useAppSelector(selectBinaries);
44
- const mappingFile = arrowToString(mappingColumn?.get(row));
45
- const functionName = arrowToString(functionNameColumn?.get(row));
46
- const cumulative = cumulativeColumn?.get(row) != null ? BigInt(cumulativeColumn?.get(row)) : 0n;
47
- const diff = diffColumn?.get(row) != null ? BigInt(diffColumn?.get(row)) : null;
48
- const filename = arrowToString(filenameColumn?.get(row));
49
- const depth = depthColumn?.get(row) ?? 0;
50
- const valueOffset = valueOffsetColumn?.get(row) !== null && valueOffsetColumn?.get(row) !== undefined
51
- ? BigInt(valueOffsetColumn?.get(row))
52
- : 0n;
46
+ // Memoize row data extraction - only changes when table or row changes
47
+ const rowData = useMemo(() => {
48
+ const mappingFile = arrowToString(columns.mapping?.get(row));
49
+ const functionName = arrowToString(columns.functionName?.get(row));
50
+ const cumulative = columns.cumulative?.get(row) != null ? BigInt(columns.cumulative?.get(row)) : 0n;
51
+ const diff = columns.diff?.get(row) != null ? BigInt(columns.diff?.get(row)) : null;
52
+ const filename = arrowToString(columns.filename?.get(row));
53
+ const depth = columns.depth?.get(row) ?? 0;
54
+ const valueOffset = columns.valueOffset?.get(row) !== null && columns.valueOffset?.get(row) !== undefined
55
+ ? BigInt(columns.valueOffset?.get(row))
56
+ : 0n;
57
+ return { mappingFile, functionName, cumulative, diff, filename, depth, valueOffset };
58
+ }, [columns, row]);
59
+ const { mappingFile, functionName, cumulative, diff, filename, depth, valueOffset } = rowData;
53
60
  const colorAttribute = colorBy === 'filename' ? filename : colorBy === 'binary' ? mappingFile : null;
54
- const hoveringName = hoveringRow !== undefined ? arrowToString(functionNameColumn?.get(hoveringRow)) : '';
61
+ // Memoize hovering name lookup
62
+ const hoveringName = useMemo(() => {
63
+ return hoveringRow !== undefined ? arrowToString(columns.functionName?.get(hoveringRow)) : '';
64
+ }, [columns.functionName, hoveringRow]);
55
65
  const shouldBeHighlighted = functionName != null && hoveringName != null && functionName === hoveringName;
56
66
  const colorResult = useNodeColor({
57
67
  isDarkMode: darkMode,
@@ -64,15 +74,43 @@ export const FlameNode = React.memo(function FlameNodeNoMemo({ table, row, color
64
74
  const name = useMemo(() => {
65
75
  return row === 0 ? 'root' : nodeLabel(table, row, binaries.length > 1);
66
76
  }, [table, row, binaries]);
77
+ // Memoize selection data - only changes when selectedRow changes
78
+ const selectionData = useMemo(() => {
79
+ const selectionOffset = columns.valueOffset?.get(selectedRow) !== null &&
80
+ columns.valueOffset?.get(selectedRow) !== undefined
81
+ ? BigInt(columns.valueOffset?.get(selectedRow))
82
+ : 0n;
83
+ const selectionCumulative = columns.cumulative?.get(selectedRow) !== null
84
+ ? BigInt(columns.cumulative?.get(selectedRow))
85
+ : 0n;
86
+ const selectedDepth = columns.depth?.get(selectedRow);
87
+ const total = columns.cumulative?.get(selectedRow);
88
+ return { selectionOffset, selectionCumulative, selectedDepth, total };
89
+ }, [columns, selectedRow]);
90
+ const { selectionOffset, selectionCumulative, selectedDepth, total } = selectionData;
91
+ // Memoize tsBounds - only changes when profileSource changes
92
+ const tsBounds = useMemo(() => boundsFromProfileSource(profileSource), [profileSource]);
93
+ // Memoize event handlers
94
+ const onMouseEnter = useCallback(() => {
95
+ setHoveringRow(row);
96
+ window.dispatchEvent(new CustomEvent(`flame-tooltip-update-${tooltipId}`, {
97
+ detail: { row },
98
+ }));
99
+ }, [setHoveringRow, row, tooltipId]);
100
+ const onMouseLeave = useCallback(() => {
101
+ setHoveringRow(undefined);
102
+ window.dispatchEvent(new CustomEvent(`flame-tooltip-update-${tooltipId}`, {
103
+ detail: { row: null },
104
+ }));
105
+ }, [setHoveringRow, tooltipId]);
106
+ const handleContextMenu = useCallback((e) => {
107
+ onContextMenu(e, row);
108
+ }, [onContextMenu, row]);
109
+ // Early returns - all hooks must be called before this point
67
110
  // Hide frames beyond effective depth limit
68
111
  if (effectiveDepth !== undefined && depth > effectiveDepth) {
69
112
  return _jsx(_Fragment, {});
70
113
  }
71
- const selectionOffset = valueOffsetColumn?.get(selectedRow) !== null &&
72
- valueOffsetColumn?.get(selectedRow) !== undefined
73
- ? BigInt(valueOffsetColumn?.get(selectedRow))
74
- : 0n;
75
- const selectionCumulative = cumulativeColumn?.get(selectedRow) !== null ? BigInt(cumulativeColumn?.get(selectedRow)) : 0n;
76
114
  if (valueOffset + cumulative <= selectionOffset ||
77
115
  valueOffset >= selectionOffset + selectionCumulative) {
78
116
  // If the end of the node is before the selection offset or the start of the node is after the selection offset + totalWidth, we don't render it.
@@ -83,8 +121,6 @@ export const FlameNode = React.memo(function FlameNodeNoMemo({ table, row, color
83
121
  return _jsx(_Fragment, {});
84
122
  }
85
123
  // Cumulative can be larger than total when a selection is made. All parents of the selection are likely larger, but we want to only show them as 100% in the graph.
86
- const tsBounds = boundsFromProfileSource(profileSource);
87
- const total = cumulativeColumn?.get(selectedRow);
88
124
  const totalRatio = cumulative > total ? 1 : Number(cumulative) / Number(total);
89
125
  const width = isFlameChart
90
126
  ? (Number(cumulative) / (Number(tsBounds[1]) - Number(tsBounds[0]))) * totalWidth
@@ -92,25 +128,9 @@ export const FlameNode = React.memo(function FlameNodeNoMemo({ table, row, color
92
128
  if (width <= 1) {
93
129
  return _jsx(_Fragment, {});
94
130
  }
95
- const selectedDepth = depthColumn?.get(selectedRow);
96
131
  const styles = selectedDepth !== undefined && selectedDepth > depth ? fadedFlameRectStyles : flameRectStyles;
97
- const onMouseEnter = () => {
98
- setHoveringRow(row);
99
- window.dispatchEvent(new CustomEvent(`flame-tooltip-update-${tooltipId}`, {
100
- detail: { row },
101
- }));
102
- };
103
- const onMouseLeave = () => {
104
- setHoveringRow(undefined);
105
- window.dispatchEvent(new CustomEvent(`flame-tooltip-update-${tooltipId}`, {
106
- detail: { row: null },
107
- }));
108
- };
109
- const handleContextMenu = (e) => {
110
- onContextMenu(e, row);
111
- };
112
- const ts = tsColumn !== null ? Number(tsColumn.get(row)) : 0;
113
- const x = isFlameChart && tsColumn !== null
132
+ const ts = columns.ts !== null ? Number(columns.ts.get(row)) : 0;
133
+ const x = isFlameChart && columns.ts !== null
114
134
  ? ((ts - Number(tsBounds[0])) / (Number(tsBounds[1]) - Number(tsBounds[0]))) * totalWidth
115
135
  : selectedDepth > depth
116
136
  ? 0
@@ -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;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"}
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;AAMtE,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,kDAkR1B,CAAC;AAEH,eAAe,eAAe,CAAC"}
@@ -14,7 +14,7 @@ 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 } from '@parca/components';
17
+ import { FlameGraphSkeleton, SandwichFlameGraphSkeleton, useParcaContext } from '@parca/components';
18
18
  import { USER_PREFERENCES, useCurrentColorProfile, useUserPreference } from '@parca/hooks';
19
19
  import { getColorForFeature, selectDarkMode, useAppSelector } from '@parca/store';
20
20
  import { useProfileFilters } from '../../ProfileView/components/ProfileFilters/useProfileFilters';
@@ -23,6 +23,7 @@ import ContextMenuWrapper from './ContextMenuWrapper';
23
23
  import { FlameNode, RowHeight } from './FlameGraphNodes';
24
24
  import { MemoizedTooltip } from './MemoizedTooltip';
25
25
  import { TooltipProvider } from './TooltipContext';
26
+ import { useBatchedRendering } from './useBatchedRendering';
26
27
  import { useScrollViewport } from './useScrollViewport';
27
28
  import { useVisibleNodes } from './useVisibleNodes';
28
29
  import { extractFeature, extractFilenameFeature, getCurrentPathFrameData, getMaxDepth, isCurrentPathFrameMatch, } from './utils';
@@ -64,7 +65,7 @@ export const getFilenameColors = (filenamesList, isDarkMode, currentColorProfile
64
65
  return colors;
65
66
  };
66
67
  const noop = () => { };
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, }) {
68
+ export const FlameGraphArrow = memo(function FlameGraphArrow({ arrow, total, filtered, width, setCurPath, curPath, profileType, profileSource, compareAbsolute, isFlameChart = false, isRenderedAsFlamegraph = false, isInSandwichView = false, isHalfScreen, tooltipId = 'default', maxFrameCount, isExpanded = false, mappingsListFromMetadata, filenamesListFromMetadata, colorBy, }) {
68
69
  const [highlightSimilarStacksPreference] = useUserPreference(USER_PREFERENCES.HIGHLIGHT_SIMILAR_STACKS.key);
69
70
  const [hoveringRow, setHoveringRow] = useState(undefined);
70
71
  const [dockedMetainfo] = useUserPreference(USER_PREFERENCES.GRAPH_METAINFO_DOCKED.key);
@@ -80,6 +81,7 @@ export const FlameGraphArrow = memo(function FlameGraphArrow({ arrow, total, fil
80
81
  const svg = useRef(null);
81
82
  const containerRef = useRef(null);
82
83
  const renderStartTime = useRef(0);
84
+ const hasInitialRenderCompleted = useRef(false);
83
85
  const [svgElement, setSvgElement] = useState(null);
84
86
  const { excludeBinary } = useProfileFilters();
85
87
  const { compareMode } = useProfileViewContext();
@@ -179,6 +181,15 @@ export const FlameGraphArrow = memo(function FlameGraphArrow({ arrow, total, fil
179
181
  selectedRow,
180
182
  effectiveDepth: deferredEffectiveDepth,
181
183
  });
184
+ // Add nodes in incremental batches to avoid blocking the UI
185
+ const { items: batchedNodes, isComplete: isBatchingComplete } = useBatchedRendering(visibleNodes, {
186
+ batchSize: 500,
187
+ });
188
+ if (isBatchingComplete) {
189
+ hasInitialRenderCompleted.current = true;
190
+ }
191
+ // Show skeleton only during initial load, not during scroll updates
192
+ const showSkeleton = !hasInitialRenderCompleted.current && batchedNodes.length !== visibleNodes.length;
182
193
  useEffect(() => {
183
194
  if (perf?.markInteraction != null) {
184
195
  renderStartTime.current = performance.now();
@@ -187,9 +198,10 @@ export const FlameGraphArrow = memo(function FlameGraphArrow({ arrow, total, fil
187
198
  useEffect(() => {
188
199
  setSvgElement(svg.current);
189
200
  }, [tooltipId]);
190
- return (_jsx(TooltipProvider, { table: table, total: total, totalUnfiltered: total + filtered, profileType: profileType, unit: arrow.unit, compareAbsolute: compareAbsolute, tooltipId: tooltipId, children: _jsxs("div", { className: "relative", children: [_jsx(ContextMenuWrapper, { ref: contextMenuRef, menuId: MENU_ID, table: table, total: total, totalUnfiltered: total + filtered, compareAbsolute: compareAbsolute, resetPath: () => setCurPath([]), hideMenu: hideAll, hideBinary: hideBinary, unit: arrow.unit, profileType: profileType, isInSandwichView: isInSandwichView }), _jsx(MemoizedTooltip, { contextElement: svgElement, dockedMetainfo: dockedMetainfo }), _jsx("div", { ref: containerRef, className: "overflow-auto scrollbar-thin scrollbar-thumb-gray-400 scrollbar-track-gray-100 dark:scrollbar-thumb-gray-600 dark:scrollbar-track-gray-800 will-change-transform scroll-smooth webkit-overflow-scrolling-touch contain", style: {
201
+ return (_jsx(TooltipProvider, { table: table, total: total, totalUnfiltered: total + filtered, profileType: profileType, unit: arrow.unit, compareAbsolute: compareAbsolute, tooltipId: tooltipId, children: _jsxs("div", { className: "relative", children: [_jsx(ContextMenuWrapper, { ref: contextMenuRef, menuId: MENU_ID, table: table, total: total, totalUnfiltered: total + filtered, compareAbsolute: compareAbsolute, resetPath: () => setCurPath([]), hideMenu: hideAll, hideBinary: hideBinary, unit: arrow.unit, profileType: profileType, isInSandwichView: isInSandwichView }), _jsx(MemoizedTooltip, { contextElement: svgElement, dockedMetainfo: dockedMetainfo }), showSkeleton && (_jsx("div", { className: "absolute inset-0 z-10", children: isRenderedAsFlamegraph ? (_jsx(SandwichFlameGraphSkeleton, { isHalfScreen: isHalfScreen, isDarkMode: isDarkMode })) : (_jsx(FlameGraphSkeleton, { isHalfScreen: isHalfScreen, isDarkMode: isDarkMode })) })), _jsx("div", { ref: containerRef, className: "overflow-auto scrollbar-thin scrollbar-thumb-gray-400 scrollbar-track-gray-100 dark:scrollbar-thumb-gray-600 dark:scrollbar-track-gray-800 will-change-transform scroll-smooth webkit-overflow-scrolling-touch contain", style: {
191
202
  width: width ?? '100%',
192
203
  contain: 'layout style paint',
193
- }, children: _jsx("svg", { className: "font-robotoMono", width: width ?? 0, height: totalHeight, preserveAspectRatio: "xMinYMid", ref: svg, children: visibleNodes.map(row => (_jsx(FlameNode, { table: table, row: row, colors: colorByColors, colorBy: colorByValue, totalWidth: width ?? 1, height: RowHeight, darkMode: isDarkMode, compareMode: compareMode, colorForSimilarNodes: colorForSimilarNodes, selectedRow: selectedRow, onClick: () => handleRowClick(row), onContextMenu: displayMenu, hoveringRow: highlightSimilarStacksPreference ? hoveringRow : undefined, setHoveringRow: highlightSimilarStacksPreference ? setHoveringRow : noop, isFlameChart: isFlameChart, profileSource: profileSource, isRenderedAsFlamegraph: isRenderedAsFlamegraph, isInSandwichView: isInSandwichView, maxDepth: maxDepth, effectiveDepth: deferredEffectiveDepth, tooltipId: tooltipId }, row))) }) })] }) }));
204
+ visibility: !showSkeleton ? 'visible' : 'hidden',
205
+ }, children: _jsx("svg", { className: "font-robotoMono", width: width ?? 0, height: totalHeight, preserveAspectRatio: "xMinYMid", ref: svg, children: batchedNodes.map(row => (_jsx(FlameNode, { table: table, row: row, colors: colorByColors, colorBy: colorByValue, totalWidth: width ?? 1, height: RowHeight, darkMode: isDarkMode, compareMode: compareMode, colorForSimilarNodes: colorForSimilarNodes, selectedRow: selectedRow, onClick: () => handleRowClick(row), onContextMenu: displayMenu, hoveringRow: highlightSimilarStacksPreference ? hoveringRow : undefined, setHoveringRow: highlightSimilarStacksPreference ? setHoveringRow : noop, isFlameChart: isFlameChart, profileSource: profileSource, isRenderedAsFlamegraph: isRenderedAsFlamegraph, isInSandwichView: isInSandwichView, maxDepth: maxDepth, effectiveDepth: deferredEffectiveDepth, tooltipId: tooltipId }, row))) }) })] }) }));
194
206
  });
195
207
  export default FlameGraphArrow;
@@ -0,0 +1,11 @@
1
+ interface UseBatchedRenderingOptions {
2
+ batchSize?: number;
3
+ batchDelay?: number;
4
+ }
5
+ interface UseBatchedRenderingResult<T> {
6
+ items: T[];
7
+ isComplete: boolean;
8
+ }
9
+ export declare const useBatchedRendering: <T>(items: T[], options?: UseBatchedRenderingOptions) => UseBatchedRenderingResult<T>;
10
+ export {};
11
+ //# sourceMappingURL=useBatchedRendering.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useBatchedRendering.d.ts","sourceRoot":"","sources":["../../../src/ProfileFlameGraph/FlameGraphArrow/useBatchedRendering.ts"],"names":[],"mappings":"AAeA,UAAU,0BAA0B;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,UAAU,yBAAyB,CAAC,CAAC;IACnC,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,UAAU,EAAE,OAAO,CAAC;CACrB;AAGD,eAAO,MAAM,mBAAmB,GAAI,CAAC,EACnC,OAAO,CAAC,EAAE,EACV,UAAS,0BAA+B,KACvC,yBAAyB,CAAC,CAAC,CAqD7B,CAAC"}
@@ -0,0 +1,65 @@
1
+ // Copyright 2022 The Parca Authors
2
+ // Licensed under the Apache License, Version 2.0 (the "License");
3
+ // you may not use this file except in compliance with the License.
4
+ // You may obtain a copy of the License at
5
+ //
6
+ // http://www.apache.org/licenses/LICENSE-2.0
7
+ //
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+ import { useEffect, useRef, useState } from 'react';
14
+ // useBatchedRendering - Helps in incrementally rendering items in batches to avoid UI blocking.
15
+ export const useBatchedRendering = (items, options = {}) => {
16
+ const { batchSize = 500, batchDelay = 0 } = options;
17
+ const [renderedCount, setRenderedCount] = useState(0);
18
+ const itemsRef = useRef(items);
19
+ const rafRef = useRef(null);
20
+ const timeoutRef = useRef(null);
21
+ useEffect(() => {
22
+ if (itemsRef.current !== items) {
23
+ itemsRef.current = items;
24
+ setRenderedCount(prev => {
25
+ if (items.length === 0)
26
+ return 0;
27
+ // If new items were added (scrolling down), keep current progress
28
+ if (items.length > prev)
29
+ return prev;
30
+ // If items reduced, cap to new length
31
+ return Math.min(prev, items.length);
32
+ });
33
+ }
34
+ }, [items]);
35
+ // Progressively render more items
36
+ useEffect(() => {
37
+ if (renderedCount === items.length) {
38
+ return;
39
+ }
40
+ const scheduleNextBatch = () => {
41
+ const incrementState = () => {
42
+ setRenderedCount(prev => Math.min(prev + batchSize, items.length));
43
+ };
44
+ if (batchDelay > 0) {
45
+ timeoutRef.current = setTimeout(incrementState, batchDelay);
46
+ }
47
+ else {
48
+ rafRef.current = requestAnimationFrame(incrementState);
49
+ }
50
+ };
51
+ scheduleNextBatch();
52
+ return () => {
53
+ if (rafRef.current !== null) {
54
+ cancelAnimationFrame(rafRef.current);
55
+ }
56
+ if (timeoutRef.current !== null) {
57
+ clearTimeout(timeoutRef.current);
58
+ }
59
+ };
60
+ }, [renderedCount, items.length, batchSize, batchDelay]);
61
+ return {
62
+ items: items.slice(0, renderedCount),
63
+ isComplete: renderedCount === items.length,
64
+ };
65
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"useScrollViewport.d.ts","sourceRoot":"","sources":["../../../src/ProfileFlameGraph/FlameGraphArrow/useScrollViewport.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,eAAO,MAAM,iBAAiB,GAAI,cAAc,KAAK,CAAC,SAAS,CAAC,cAAc,CAAC,KAAG,aAkEjF,CAAC"}
1
+ {"version":3,"file":"useScrollViewport.d.ts","sourceRoot":"","sources":["../../../src/ProfileFlameGraph/FlameGraphArrow/useScrollViewport.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;CACxB;AAiBD,eAAO,MAAM,iBAAiB,GAAI,cAAc,KAAK,CAAC,SAAS,CAAC,cAAc,CAAC,KAAG,aAsFjF,CAAC"}
@@ -11,6 +11,21 @@
11
11
  // See the License for the specific language governing permissions and
12
12
  // limitations under the License.
13
13
  import { useCallback, useEffect, useRef, useState } from 'react';
14
+ // Find the scrollable ancestor (the element with overflow: auto/scroll)
15
+ const findScrollableParent = (element) => {
16
+ if (element === null)
17
+ return undefined;
18
+ let current = element.parentElement;
19
+ while (current !== null) {
20
+ const style = window.getComputedStyle(current);
21
+ const overflowY = style.overflowY;
22
+ if (overflowY === 'auto' || overflowY === 'scroll') {
23
+ return current;
24
+ }
25
+ current = current.parentElement;
26
+ }
27
+ return undefined;
28
+ };
14
29
  export const useScrollViewport = (containerRef) => {
15
30
  const [viewport, setViewport] = useState({
16
31
  scrollTop: 0,
@@ -22,10 +37,22 @@ export const useScrollViewport = (containerRef) => {
22
37
  const updateViewport = useCallback(() => {
23
38
  if (containerRef.current !== null) {
24
39
  const container = containerRef.current;
40
+ const rect = container.getBoundingClientRect();
41
+ // Restrict container height to the visible portion on screen
42
+ // This handles cases where the container is partially off-screen
43
+ // We only want to consider the visible part for culling calculations
44
+ const containerTop = rect.top;
45
+ const containerBottom = rect.bottom;
46
+ const viewportTop = 0;
47
+ const viewportBottom = window.innerHeight;
48
+ const visibleTop = Math.max(containerTop, viewportTop);
49
+ const visibleBottom = Math.min(containerBottom, viewportBottom);
50
+ const visibleHeight = Math.max(0, visibleBottom - visibleTop);
51
+ const scrollOffset = Math.max(0, viewportTop - containerTop);
25
52
  const newViewport = {
26
- scrollTop: container.scrollTop,
53
+ scrollTop: scrollOffset,
27
54
  scrollLeft: container.scrollLeft,
28
- containerHeight: container.clientHeight,
55
+ containerHeight: visibleHeight, // Only the visible portion
29
56
  containerWidth: container.clientWidth,
30
57
  };
31
58
  setViewport(newViewport);
@@ -44,22 +71,25 @@ export const useScrollViewport = (containerRef) => {
44
71
  const container = containerRef.current;
45
72
  if (container === null)
46
73
  return;
74
+ const scrollableParent = findScrollableParent(container);
47
75
  // ResizeObserver Strategy:
48
76
  // Monitor container size changes (window resize, layout shifts)
49
77
  // to update viewport dimensions for accurate culling calculations
50
78
  const resizeObserver = new ResizeObserver(() => {
51
79
  throttledUpdateViewport();
52
80
  });
53
- // Container Scroll Event Strategy:
54
- // Use passive event listeners for better scroll performance
55
- // Throttle with requestAnimationFrame to maintain 60fps target
81
+ // Listen to scroll on the actual scrollable parent
82
+ scrollableParent?.addEventListener('scroll', throttledUpdateViewport, { passive: true });
56
83
  container.addEventListener('scroll', throttledUpdateViewport, { passive: true });
84
+ window.addEventListener('scroll', throttledUpdateViewport, { passive: true });
57
85
  resizeObserver.observe(container);
58
86
  // Initialize viewport state on mount
59
87
  updateViewport();
60
88
  return () => {
61
89
  // Cleanup: Remove event listeners and cancel pending animations
90
+ scrollableParent?.removeEventListener('scroll', throttledUpdateViewport);
62
91
  container.removeEventListener('scroll', throttledUpdateViewport);
92
+ window.removeEventListener('scroll', throttledUpdateViewport);
63
93
  resizeObserver.disconnect();
64
94
  if (throttleRef.current !== null) {
65
95
  cancelAnimationFrame(throttleRef.current);
@@ -1 +1 @@
1
- {"version":3,"file":"useVisibleNodes.d.ts","sourceRoot":"","sources":["../../../src/ProfileFlameGraph/FlameGraphArrow/useVisibleNodes.ts"],"names":[],"mappings":"AAeA,OAAO,EAAC,KAAK,EAAC,MAAM,cAAc,CAAC;AAInC,OAAO,EAAC,aAAa,EAAC,MAAM,qBAAqB,CAAC;AAiClD,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IAClB,QAAQ,EAAE,aAAa,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,eAAe,GAAI,iEAO7B,qBAAqB,KAAG,MAAM,EAwFhC,CAAC"}
1
+ {"version":3,"file":"useVisibleNodes.d.ts","sourceRoot":"","sources":["../../../src/ProfileFlameGraph/FlameGraphArrow/useVisibleNodes.ts"],"names":[],"mappings":"AAeA,OAAO,EAAC,KAAK,EAAC,MAAM,cAAc,CAAC;AAInC,OAAO,EAAC,aAAa,EAAC,MAAM,qBAAqB,CAAC;AAiClD,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IAClB,QAAQ,EAAE,aAAa,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,eAAe,GAAI,iEAO7B,qBAAqB,KAAG,MAAM,EA4HhC,CAAC"}
@@ -53,22 +53,48 @@ const useDepthBuckets = (table) => {
53
53
  export const useVisibleNodes = ({ table, viewport, total, width, selectedRow, effectiveDepth, }) => {
54
54
  const depthBuckets = useDepthBuckets(table);
55
55
  const lastResultRef = useRef({ key: '', result: [] });
56
+ const renderedRangeRef = useRef({
57
+ minDepth: Infinity,
58
+ maxDepth: -Infinity,
59
+ table: null,
60
+ });
56
61
  return useMemo(() => {
62
+ // This happens when the continer is scrolled off screen, in this case we return all previously rendered nodes
63
+ // to avoid trimming the rendered nodes to zero which would cause jank when scrolling back into view
64
+ if (viewport.containerHeight === 0 && lastResultRef.current.result.length > 0) {
65
+ return lastResultRef.current.result;
66
+ }
57
67
  // Create a stable key for memoization to prevent unnecessary recalculations
58
68
  const memoKey = `${viewport.scrollTop}-${viewport.containerHeight}-${selectedRow}-${effectiveDepth}-${width}-${Number(total)}-${table.numRows}`;
59
69
  // Return cached result if viewport hasn't meaningfully changed
60
70
  if (lastResultRef.current.key === memoKey) {
61
71
  return lastResultRef.current.result;
62
72
  }
63
- if (table === null || viewport.containerHeight === 0)
73
+ if (table === null)
64
74
  return [];
65
75
  const visibleRows = [];
66
76
  const { scrollTop, containerHeight } = viewport;
67
77
  // Viewport Culling Algorithm:
68
78
  // 1. Calculate visible depth range based on scroll position and container height
69
79
  // 2. Add 5-row buffer above/below for smooth scrolling experience
70
- const startDepth = Math.max(0, Math.floor(scrollTop / RowHeight) - 5);
71
- const endDepth = Math.min(effectiveDepth, Math.ceil((scrollTop + containerHeight) / RowHeight) + 5);
80
+ // Note: We never shrink the rendered range to avoid back and forth node removals (and in turn additions when scrolled down again) to the dom.
81
+ const BUFFER = 15; // Buffer for smoother scrolling
82
+ const visibleStartDepth = Math.max(0, Math.floor(scrollTop / RowHeight) - BUFFER);
83
+ const visibleDepths = Math.ceil(containerHeight / RowHeight);
84
+ const visibleEndDepth = Math.min(effectiveDepth, visibleStartDepth + visibleDepths + BUFFER);
85
+ // Reset range if table changed (new data loaded) as this is new data
86
+ if (renderedRangeRef.current.table !== table) {
87
+ renderedRangeRef.current = {
88
+ minDepth: Infinity,
89
+ maxDepth: -Infinity,
90
+ table: table,
91
+ };
92
+ }
93
+ // Expand the rendered range (never shrink when scrolling up/down)
94
+ renderedRangeRef.current.minDepth = Math.min(renderedRangeRef.current.minDepth, visibleStartDepth);
95
+ renderedRangeRef.current.maxDepth = Math.max(renderedRangeRef.current.maxDepth, visibleEndDepth);
96
+ const startDepth = renderedRangeRef.current.minDepth;
97
+ const endDepth = renderedRangeRef.current.maxDepth;
72
98
  const cumulativeColumn = table.getChild(FIELD_CUMULATIVE);
73
99
  const valueOffsetColumn = table.getChild(FIELD_VALUE_OFFSET);
74
100
  const selectionOffset = valueOffsetColumn?.get(selectedRow) !== null &&
@@ -10,7 +10,7 @@ interface MetricsGraphSectionProps {
10
10
  querySelection: QuerySelection;
11
11
  profileSelection: ProfileSelection | null;
12
12
  comparing: boolean;
13
- sumBy: string[] | null;
13
+ sumBy: string[] | undefined;
14
14
  defaultSumByLoading: boolean;
15
15
  queryClient: QueryServiceClient;
16
16
  queryExpressionString: string;
@@ -1 +1 @@
1
- {"version":3,"file":"MetricsGraphSection.d.ts","sourceRoot":"","sources":["../../src/ProfileSelector/MetricsGraphSection.tsx"],"names":[],"mappings":"AAeA,OAAO,EAAQ,kBAAkB,EAAC,MAAM,eAAe,CAAC;AACxD,OAAO,EAAC,aAAa,EAAmB,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAC,KAAK,EAAC,MAAM,eAAe,CAAC;AAEpC,OAAO,EAAC,gBAAgB,EAAC,MAAM,IAAI,CAAC;AAGpC,OAAO,EAAC,cAAc,EAAC,MAAM,SAAS,CAAC;AAEvC,UAAU,wBAAwB;IAChC,gBAAgB,EAAE,OAAO,CAAC;IAC1B,gCAAgC,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAC3D,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,cAAc,CAAC;IAC/B,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC1C,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACvB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,WAAW,EAAE,kBAAkB,CAAC;IAChC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,qBAAqB,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IACtD,WAAW,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAC7C,mBAAmB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAChF,KAAK,EAAE,KAAK,CAAC;IACb,qBAAqB,EAAE,CAAC,eAAe,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,kBAAkB,EAAE,CAAC,QAAQ,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACjD,WAAW,EAAE,CACX,kBAAkB,CAAC,EAAE;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAC,EACtE,UAAU,CAAC,EAAE,MAAM,KAChB,IAAI,CAAC;CACX;AAED,wBAAgB,mBAAmB,CAAC,EAClC,gBAAgB,EAChB,gCAAgC,EAChC,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,SAAS,EACT,KAAK,EACL,mBAAmB,EACnB,WAAW,EACX,qBAAqB,EACrB,qBAAqB,EACrB,WAAW,EACX,mBAAmB,EACnB,KAAK,EACL,qBAAqB,EACrB,WAAW,GACZ,EAAE,wBAAwB,GAAG,GAAG,CAAC,OAAO,CA+HxC"}
1
+ {"version":3,"file":"MetricsGraphSection.d.ts","sourceRoot":"","sources":["../../src/ProfileSelector/MetricsGraphSection.tsx"],"names":[],"mappings":"AAeA,OAAO,EAAQ,kBAAkB,EAAC,MAAM,eAAe,CAAC;AACxD,OAAO,EAAC,aAAa,EAAmB,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAC,KAAK,EAAC,MAAM,eAAe,CAAC;AAEpC,OAAO,EAAC,gBAAgB,EAAC,MAAM,IAAI,CAAC;AAGpC,OAAO,EAAC,cAAc,EAAC,MAAM,SAAS,CAAC;AAEvC,UAAU,wBAAwB;IAChC,gBAAgB,EAAE,OAAO,CAAC;IAC1B,gCAAgC,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAC3D,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,cAAc,CAAC;IAC/B,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC1C,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAC5B,mBAAmB,EAAE,OAAO,CAAC;IAC7B,WAAW,EAAE,kBAAkB,CAAC;IAChC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,qBAAqB,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IACtD,WAAW,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAC7C,mBAAmB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAChF,KAAK,EAAE,KAAK,CAAC;IACb,qBAAqB,EAAE,CAAC,eAAe,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD,kBAAkB,EAAE,CAAC,QAAQ,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACjD,WAAW,EAAE,CACX,kBAAkB,CAAC,EAAE;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAC,EACtE,UAAU,CAAC,EAAE,MAAM,KAChB,IAAI,CAAC;CACX;AAED,wBAAgB,mBAAmB,CAAC,EAClC,gBAAgB,EAChB,gCAAgC,EAChC,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,SAAS,EACT,KAAK,EACL,mBAAmB,EACnB,WAAW,EACX,qBAAqB,EACrB,qBAAqB,EACrB,WAAW,EACX,mBAAmB,EACnB,KAAK,EACL,qBAAqB,EACrB,WAAW,GACZ,EAAE,wBAAwB,GAAG,GAAG,CAAC,OAAO,CA+HxC"}
@@ -84,5 +84,5 @@ export function MetricsGraphSection({ showMetricsGraph, setDisplayHideMetricsGra
84
84
  };
85
85
  return (_jsxs("div", { className: cx('relative', { 'py-4': !showMetricsGraph }), children: [setDisplayHideMetricsGraphButton != null ? (_jsxs("button", { onClick: () => setDisplayHideMetricsGraphButton(!showMetricsGraph), className: cx('hidden px-3 py-1 text-sm font-medium text-gray-700 dark:text-gray-200 bg-gray-100 rounded-md hover:bg-gray-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:bg-gray-900 z-[5]', showMetricsGraph && 'absolute right-0 bottom-3 !flex', !showMetricsGraph && 'relative !flex ml-auto'), children: [showMetricsGraph ? 'Hide' : 'Show', " Metrics Graph"] })) : null, showMetricsGraph && (_jsx(_Fragment, { children: _jsx("div", { style: { height: heightStyle }, children: (querySelection.expression !== '' || defaultSumByLoading) &&
86
86
  querySelection.from !== undefined &&
87
- querySelection.to !== undefined ? (_jsx(_Fragment, { children: _jsx(ProfileMetricsGraph, { queryClient: queryClient, queryExpression: querySelection.expression, from: querySelection.from, to: querySelection.to, profile: profileSelection, comparing: comparing, sumBy: querySelection.sumBy ?? sumBy ?? [], sumByLoading: defaultSumByLoading, setTimeRange: handleTimeRangeChange, addLabelMatcher: addLabelMatcher, onPointClick: handlePointClick }) })) : (profileSelection === null && (_jsx("div", { className: "p-2", children: _jsx(ProfileMetricsEmptyState, { message: "Please select a profile type and click 'Search' to begin." }) }))) }) }))] }));
87
+ querySelection.to !== undefined ? (_jsx(_Fragment, { children: _jsx(ProfileMetricsGraph, { queryClient: queryClient, queryExpression: querySelection.expression, from: querySelection.from, to: querySelection.to, profile: profileSelection, comparing: comparing, sumBy: sumBy ?? [], sumByLoading: defaultSumByLoading, setTimeRange: handleTimeRangeChange, addLabelMatcher: addLabelMatcher, onPointClick: handlePointClick }) })) : (profileSelection === null && (_jsx("div", { className: "p-2", children: _jsx(ProfileMetricsEmptyState, { message: "Please select a profile type and click 'Search' to begin." }) }))) }) }))] }));
88
88
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileSelector/index.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAC,QAAQ,EAAE,cAAc,EAAoD,MAAM,OAAO,CAAC;AAElG,OAAO,EAAC,QAAQ,EAAC,MAAM,0BAA0B,CAAC;AAElD,OAAO,EAAsB,oBAAoB,EAAE,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAY5F,OAAO,EAAyB,KAAK,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAY/E,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,uBAAuB;IAC/B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,2BAA2B,CAAC,EAAE,OAAO,CAAC;CACvC;AAED,UAAU,oBAAqB,SAAQ,uBAAuB;IAC5D,WAAW,EAAE,kBAAkB,CAAC;IAChC,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,gBAAgB,CAAC;IAC7B,gCAAgC,CAAC,EAAE,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IACrE,MAAM,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,oBAAoB,CAAC;IAC5B,KAAK,CAAC,EAAE,QAAQ,CAAC;CAClB;AAED,eAAO,MAAM,eAAe,GAC1B,QAAQ,kBAAkB,EAC1B,QAAQ,MAAM,EACd,MAAM,MAAM,KACX,mBAsBF,CAAC;AAEF,QAAA,MAAM,eAAe,GAAI,kMAYtB,oBAAoB,KAAG,GAAG,CAAC,OAyO7B,CAAC;AAEF,eAAe,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileSelector/index.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAC,QAAQ,EAAE,cAAc,EAAoD,MAAM,OAAO,CAAC;AAElG,OAAO,EAAC,QAAQ,EAAC,MAAM,0BAA0B,CAAC;AAElD,OAAO,EAAsB,oBAAoB,EAAE,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAY5F,OAAO,EAAyB,KAAK,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAY/E,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,uBAAuB;IAC/B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,2BAA2B,CAAC,EAAE,OAAO,CAAC;CACvC;AAED,UAAU,oBAAqB,SAAQ,uBAAuB;IAC5D,WAAW,EAAE,kBAAkB,CAAC;IAChC,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,gBAAgB,CAAC;IAC7B,gCAAgC,CAAC,EAAE,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;IACrE,MAAM,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,oBAAoB,CAAC;IAC5B,KAAK,CAAC,EAAE,QAAQ,CAAC;CAClB;AAED,eAAO,MAAM,eAAe,GAC1B,QAAQ,kBAAkB,EAC1B,QAAQ,MAAM,EACd,MAAM,MAAM,KACX,mBAsBF,CAAC;AAEF,QAAA,MAAM,eAAe,GAAI,kMAYtB,oBAAoB,KAAG,GAAG,CAAC,OAqO7B,CAAC;AAEF,eAAe,eAAe,CAAC"}
@@ -101,7 +101,6 @@ const ProfileSelector = ({ queryClient, closeProfile, enforcedProfileName, compa
101
101
  const currentTo = timeRangeSelection.getToMs(true);
102
102
  const currentRangeKey = timeRangeSelection.getRangeKey();
103
103
  // Commit with refreshed time range
104
- console.log('[draftExpression] setQueryExpression: committing with refreshed time range:', draftSelection.expression);
105
104
  commitDraft({
106
105
  from: currentFrom,
107
106
  to: currentTo,
@@ -150,7 +149,7 @@ const ProfileSelector = ({ queryClient, closeProfile, enforcedProfileName, compa
150
149
  queryExpressionString === '{}';
151
150
  const queryBrowserRef = useRef(null);
152
151
  const sumByRef = useRef(null);
153
- return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "mb-2 flex", children: [_jsx(LabelsQueryProvider, { setMatchersString: setMatchersString, runQuery: setQueryExpression, currentQuery: query, profileType: selectedProfileName ?? profileType.toString(), queryClient: queryClient, start: timeRangeSelection.getFromMs(), end: timeRangeSelection.getToMs(), suffix: suffix, children: _jsx(LabelsSource, { children: _jsx(QueryControls, { showProfileTypeSelector: showProfileTypeSelector, showSumBySelector: showSumBySelector, profileTypesData: profileTypesData, profileTypesLoading: profileTypesLoading, selectedProfileName: selectedProfileName, setProfileName: setProfileName, setMatchersString: setMatchersString, setQueryExpression: setQueryExpression, query: query, queryBrowserRef: queryBrowserRef, timeRangeSelection: timeRangeSelection, setTimeRangeSelection: handleTimeRangeChange, searchDisabled: searchDisabled, setQueryBrowserMode: setQueryBrowserMode, advancedModeForQueryBrowser: advancedModeForQueryBrowser, setAdvancedModeForQueryBrowser: setAdvancedModeForQueryBrowser, queryClient: queryClient, sumByRef: sumByRef, labels: labels, sumBySelection: draftSelection.sumBy ?? [], sumBySelectionLoading: sumByLoading, setUserSumBySelection: setDraftSumBy, profileType: profileType, profileTypesError: error, viewComponent: viewComponent, draftSelection: draftSelection, setDraftMatchers: setDraftMatchers, draftParsedQuery: draftParsedQuery, commitDraft: commitDraft }) }) }), comparing && (_jsx("div", { children: _jsx(IconButton, { onClick: () => closeProfile(), icon: _jsx(CloseIcon, {}), ...testId(TEST_IDS.COMPARE_CLOSE_BUTTON) }) }))] }), _jsx(MetricsGraphSection, { showMetricsGraph: showMetricsGraph, setDisplayHideMetricsGraphButton: setDisplayHideMetricsGraphButton, heightStyle: heightStyle, querySelection: querySelection, profileSelection: profileSelection, comparing: comparing, sumBy: querySelection.sumBy ?? [], defaultSumByLoading: sumByLoading, queryClient: queryClient, queryExpressionString: queryExpressionString, setTimeRangeSelection: handleTimeRangeChange, selectQuery: commitDraft, setProfileSelection: setProfileSelection, query: query, setQueryExpression: setQueryExpression, setNewQueryExpression: setDraftExpression, commitDraft: commitDraft })] }));
152
+ return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "mb-2 flex", children: [_jsx(LabelsQueryProvider, { setMatchersString: setMatchersString, runQuery: setQueryExpression, currentQuery: query, profileType: selectedProfileName ?? profileType.toString(), queryClient: queryClient, start: timeRangeSelection.getFromMs(), end: timeRangeSelection.getToMs(), suffix: suffix, children: _jsx(LabelsSource, { children: _jsx(QueryControls, { showProfileTypeSelector: showProfileTypeSelector, showSumBySelector: showSumBySelector, profileTypesData: profileTypesData, profileTypesLoading: profileTypesLoading, selectedProfileName: selectedProfileName, setProfileName: setProfileName, setMatchersString: setMatchersString, setQueryExpression: setQueryExpression, query: query, queryBrowserRef: queryBrowserRef, timeRangeSelection: timeRangeSelection, setTimeRangeSelection: handleTimeRangeChange, searchDisabled: searchDisabled, setQueryBrowserMode: setQueryBrowserMode, advancedModeForQueryBrowser: advancedModeForQueryBrowser, setAdvancedModeForQueryBrowser: setAdvancedModeForQueryBrowser, queryClient: queryClient, sumByRef: sumByRef, labels: labels, sumBySelection: draftSelection.sumBy ?? [], sumBySelectionLoading: sumByLoading, setUserSumBySelection: setDraftSumBy, profileType: profileType, profileTypesError: error, viewComponent: viewComponent, draftSelection: draftSelection, setDraftMatchers: setDraftMatchers, draftParsedQuery: draftParsedQuery, commitDraft: commitDraft }) }) }), comparing && (_jsx("div", { children: _jsx(IconButton, { onClick: () => closeProfile(), icon: _jsx(CloseIcon, {}), ...testId(TEST_IDS.COMPARE_CLOSE_BUTTON) }) }))] }), _jsx(MetricsGraphSection, { showMetricsGraph: showMetricsGraph, setDisplayHideMetricsGraphButton: setDisplayHideMetricsGraphButton, heightStyle: heightStyle, querySelection: querySelection, profileSelection: profileSelection, comparing: comparing, sumBy: querySelection.sumBy, defaultSumByLoading: sumByLoading, queryClient: queryClient, queryExpressionString: queryExpressionString, setTimeRangeSelection: handleTimeRangeChange, selectQuery: commitDraft, setProfileSelection: setProfileSelection, query: query, setQueryExpression: setQueryExpression, setNewQueryExpression: setDraftExpression, commitDraft: commitDraft })] }));
154
153
  };
155
154
  export default ProfileSelector;
156
155
  const LabelsSource = ({ children }) => {
@@ -1 +1 @@
1
- {"version":3,"file":"useResetStateOnProfileTypeChange.d.ts","sourceRoot":"","sources":["../../../src/ProfileView/hooks/useResetStateOnProfileTypeChange.ts"],"names":[],"mappings":"AAiBA,eAAO,MAAM,gCAAgC,QAAO,CAAC,MAAM,IAAI,CAuB9D,CAAC"}
1
+ {"version":3,"file":"useResetStateOnProfileTypeChange.d.ts","sourceRoot":"","sources":["../../../src/ProfileView/hooks/useResetStateOnProfileTypeChange.ts"],"names":[],"mappings":"AAiBA,eAAO,MAAM,gCAAgC,QAAO,CAAC,MAAM,IAAI,CA+B9D,CAAC"}
@@ -15,6 +15,8 @@ import { useProfileFilters } from '../components/ProfileFilters/useProfileFilter
15
15
  export const useResetStateOnProfileTypeChange = () => {
16
16
  const [groupBy, setGroupBy] = useURLState('group_by');
17
17
  const [curPath, setCurPath] = useURLState('cur_path');
18
+ const [sumByA, setSumByA] = useURLState('sum_by_a');
19
+ const [sumByB, setSumByB] = useURLState('sum_by_b');
18
20
  const { resetFilters } = useProfileFilters();
19
21
  const [sandwichFunctionName, setSandwichFunctionName] = useURLState('sandwich_function_name');
20
22
  const batchUpdates = useURLStateBatch();
@@ -30,6 +32,12 @@ export const useResetStateOnProfileTypeChange = () => {
30
32
  if (sandwichFunctionName !== undefined) {
31
33
  setSandwichFunctionName(undefined);
32
34
  }
35
+ if (sumByA !== undefined) {
36
+ setSumByA(undefined);
37
+ }
38
+ if (sumByB !== undefined) {
39
+ setSumByB(undefined);
40
+ }
33
41
  resetFilters();
34
42
  });
35
43
  };
@@ -1 +1 @@
1
- {"version":3,"file":"Select.d.ts","sourceRoot":"","sources":["../../src/SimpleMatchers/Select.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAiD,MAAM,OAAO,CAAC;AAStE,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC;IACpB,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,aAAa,CAAC;CACxB;AAED,MAAM,WAAW,eAAgB,SAAQ,UAAU;IACjD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,EAAE,CAAC;CACtB;AAED,UAAU,iBAAiB;IACzB,KAAK,EAAE,iBAAiB,EAAE,GAAG,UAAU,EAAE,CAAC;IAC1C,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;IACnB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED,QAAA,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAwUnE,CAAC;AAkDF,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"Select.d.ts","sourceRoot":"","sources":["../../src/SimpleMatchers/Select.tsx"],"names":[],"mappings":"AAaA,OAAO,KAA2D,MAAM,OAAO,CAAC;AAShF,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC;IACpB,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,aAAa,CAAC;CACxB;AAED,MAAM,WAAW,eAAgB,SAAQ,UAAU;IACjD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,EAAE,CAAC;CACtB;AAED,UAAU,iBAAiB;IACzB,KAAK,EAAE,iBAAiB,EAAE,GAAG,UAAU,EAAE,CAAC;IAC1C,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;IACnB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED,QAAA,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAwUnE,CAAC;AAkDF,eAAe,YAAY,CAAC"}