@parca/profile 0.16.145 → 0.16.147

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,14 @@
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.16.147](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.146...@parca/profile@0.16.147) (2023-03-22)
7
+
8
+ **Note:** Version bump only for package @parca/profile
9
+
10
+ ## [0.16.146](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.145...@parca/profile@0.16.146) (2023-03-22)
11
+
12
+ **Note:** Version bump only for package @parca/profile
13
+
6
14
  ## [0.16.145](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.144...@parca/profile@0.16.145) (2023-03-21)
7
15
 
8
16
  **Note:** Version bump only for package @parca/profile
@@ -109,6 +109,6 @@ var Callgraph = function (_a) {
109
109
  var isResetViewButtonEnabled = view.scale !== originalView.scale ||
110
110
  view.translation.x !== originalView.translation.x ||
111
111
  view.translation.y !== originalView.translation.y;
112
- return (_jsxs("div", __assign({ className: "w-full relative" }, { children: [_jsxs("div", __assign({ ref: containerRef, className: "w-full overflow-hidden" }, { children: [_jsx(MapInteractionCSS, __assign({ showControls: true, minScale: 1, maxScale: 5, value: view, onChange: function (value) { return setView(value); } }, { children: _jsx(SVG, { ref: svgWrapper, src: svgString, width: width, height: "auto", title: "Callgraph", innerRef: svgRef }) })), svgRef.current !== null && (_jsx(GraphTooltip, { type: "callgraph", unit: sampleUnit, total: parseInt(data.cumulative), contextElement: containerRef.current }))] })), _jsx("div", __assign({ className: cx(dashboardItems.length > 1 ? 'left-[25px]' : 'left-0', 'w-auto absolute top-[-46px]') }, { children: _jsx(Button, __assign({ variant: "neutral", onClick: resetView, className: "z-50", disabled: !isResetViewButtonEnabled }, { children: "Reset View" })) }))] })));
112
+ return (_jsxs("div", __assign({ className: "w-full relative" }, { children: [_jsxs("div", __assign({ ref: containerRef, className: "w-full overflow-hidden" }, { children: [_jsx(MapInteractionCSS, __assign({ showControls: true, minScale: 1, maxScale: 5, value: view, onChange: function (value) { return setView(value); } }, { children: _jsx(SVG, { ref: svgWrapper, src: svgString, width: width, height: "auto", title: "Callgraph", innerRef: svgRef }) })), svgRef.current !== null && (_jsx(GraphTooltip, { type: "callgraph", unit: sampleUnit, total: parseInt(data.cumulative), totalUnfiltered: parseInt(data.cumulative), contextElement: containerRef.current }))] })), _jsx("div", __assign({ className: cx(dashboardItems.length > 1 ? 'left-[25px]' : 'left-0', 'w-auto absolute top-[-46px]') }, { children: _jsx(Button, __assign({ variant: "neutral", onClick: resetView, className: "z-50", disabled: !isResetViewButtonEnabled }, { children: "Reset View" })) }))] })));
113
113
  };
114
114
  export default Callgraph;
@@ -14,6 +14,7 @@ interface GraphTooltipProps {
14
14
  y?: number;
15
15
  unit: string;
16
16
  total: number;
17
+ totalUnfiltered: number;
17
18
  hoveringNode?: HoveringNode;
18
19
  contextElement: Element | null;
19
20
  isFixed?: boolean;
@@ -24,10 +25,11 @@ interface GraphTooltipProps {
24
25
  functions?: ParcaFunction[];
25
26
  type?: string;
26
27
  }
27
- export declare const GraphTooltipContent: ({ hoveringNode, unit, total, isFixed, strings, mappings, locations, functions, type, }: {
28
+ export declare const GraphTooltipContent: ({ hoveringNode, unit, total, totalUnfiltered, isFixed, strings, mappings, locations, functions, type, }: {
28
29
  hoveringNode: HoveringNode;
29
30
  unit: string;
30
31
  total: number;
32
+ totalUnfiltered: number;
31
33
  isFixed: boolean;
32
34
  strings?: string[] | undefined;
33
35
  mappings?: Mapping[] | undefined;
@@ -35,5 +37,5 @@ export declare const GraphTooltipContent: ({ hoveringNode, unit, total, isFixed,
35
37
  functions?: ParcaFunction[] | undefined;
36
38
  type?: string | undefined;
37
39
  }) => JSX.Element;
38
- declare const GraphTooltip: ({ x, y, unit, total, hoveringNode: hoveringNodeProp, contextElement, isFixed, virtualContextElement, strings, mappings, locations, functions, type, }: GraphTooltipProps) => JSX.Element;
40
+ declare const GraphTooltip: ({ x, y, unit, total, totalUnfiltered, hoveringNode: hoveringNodeProp, contextElement, isFixed, virtualContextElement, strings, mappings, locations, functions, type, }: GraphTooltipProps) => JSX.Element;
39
41
  export default GraphTooltip;
@@ -129,7 +129,7 @@ var TooltipMetaInfo = function (_a) {
129
129
  };
130
130
  var timeoutHandle = null;
131
131
  export var GraphTooltipContent = function (_a) {
132
- var hoveringNode = _a.hoveringNode, unit = _a.unit, total = _a.total, isFixed = _a.isFixed, strings = _a.strings, mappings = _a.mappings, locations = _a.locations, functions = _a.functions, _b = _a.type, type = _b === void 0 ? 'flamegraph' : _b;
132
+ var hoveringNode = _a.hoveringNode, unit = _a.unit, total = _a.total, totalUnfiltered = _a.totalUnfiltered, isFixed = _a.isFixed, strings = _a.strings, mappings = _a.mappings, locations = _a.locations, functions = _a.functions, _b = _a.type, type = _b === void 0 ? 'flamegraph' : _b;
133
133
  var _c = useState(false), isCopied = _c[0], setIsCopied = _c[1];
134
134
  var onCopy = function () {
135
135
  setIsCopied(true);
@@ -147,14 +147,17 @@ export var GraphTooltipContent = function (_a) {
147
147
  var diffPercentageText = diffSign + (diffRatio * 100).toFixed(2) + '%';
148
148
  var diffText = "".concat(diffValueText, " (").concat(diffPercentageText, ")");
149
149
  var getTextForCumulative = function (hoveringNodeCumulative) {
150
- return "".concat(valueFormatter(hoveringNodeCumulative, unit, 2), " (\n ").concat(((hoveringNodeCumulative * 100) / total).toFixed(2), "%)");
150
+ var filtered = totalUnfiltered > total
151
+ ? " / ".concat(((hoveringNodeCumulative * 100) / total).toFixed(2), "% of filtered")
152
+ : '';
153
+ return "".concat(valueFormatter(hoveringNodeCumulative, unit, 2), "\n (").concat(((hoveringNodeCumulative * 100) / totalUnfiltered).toFixed(2), "%").concat(filtered, ")");
151
154
  };
152
155
  return (_jsx("div", __assign({ className: "text-sm flex ".concat(isFixed ? 'w-full' : '') }, { children: _jsx("div", __assign({ className: "m-auto w-full ".concat(isFixed ? 'w-full' : '') }, { children: _jsxs("div", __assign({ className: "border border-gray-300 dark:border-gray-500 bg-gray-50 dark:bg-gray-900 rounded-lg p-3 shadow-lg min-h-52 w-[500px] flex justify-between flex-col" }, { children: [_jsx("div", __assign({ className: "flex flex-row" }, { children: _jsxs("div", __assign({ className: "mx-2" }, { children: [_jsx("div", __assign({ className: "font-semibold break-all h-10 flex items-center" }, { children: hoveringNode.meta === undefined ? (_jsx("p", { children: "root" })) : (_jsx(_Fragment, { children: hoveringNode.meta.function !== undefined &&
153
156
  hoveringNode.meta.function.name !== '' ? (_jsx(CopyToClipboard, __assign({ onCopy: onCopy, text: hoveringNode.meta.function.name }, { children: _jsx("button", __assign({ className: "cursor-pointer text-left" }, { children: hoveringNode.meta.function.name })) }))) : (_jsx(_Fragment, { children: hoveringNode.meta.location !== undefined &&
154
157
  parseInt(hoveringNode.meta.location.address, 10) !== 0 ? (_jsx(CopyToClipboard, __assign({ onCopy: onCopy, text: hexifyAddress(hoveringNode.meta.location.address) }, { children: _jsx("button", __assign({ className: "cursor-pointer text-left" }, { children: hexifyAddress(hoveringNode.meta.location.address) })) }))) : (_jsx("p", { children: "unknown" })) })) })) })), _jsx("table", __assign({ className: "table-fixed pr-0 text-gray-700 dark:text-gray-300 my-2 w-full" }, { children: _jsxs("tbody", { children: [_jsxs("tr", { children: [_jsx("td", __assign({ className: "w-1/4" }, { children: "Cumulative" })), _jsx("td", __assign({ className: "w-3/4" }, { children: _jsx(CopyToClipboard, __assign({ onCopy: onCopy, text: getTextForCumulative(hoveringNodeCumulative) }, { children: _jsx("button", __assign({ className: "cursor-pointer" }, { children: getTextForCumulative(hoveringNodeCumulative) })) })) }))] }), hoveringNode.diff !== undefined && diff !== 0 && (_jsxs("tr", { children: [_jsx("td", __assign({ className: "w-1/4" }, { children: "Diff" })), _jsx("td", __assign({ className: "w-3/4" }, { children: _jsx(CopyToClipboard, __assign({ onCopy: onCopy, text: diffText }, { children: _jsx("button", __assign({ className: "cursor-pointer" }, { children: diffText })) })) }))] })), _jsx(TooltipMetaInfo, { onCopy: onCopy, hoveringNode: hoveringNode, strings: strings, mappings: mappings, locations: locations, functions: functions, type: type })] }) }))] })) })), _jsx("span", __assign({ className: "block text-gray-500 text-xs mx-2" }, { children: isCopied ? 'Copied!' : 'Hold shift and click on a value to copy.' }))] })) })) })));
155
158
  };
156
159
  var GraphTooltip = function (_a) {
157
- var x = _a.x, y = _a.y, unit = _a.unit, total = _a.total, hoveringNodeProp = _a.hoveringNode, contextElement = _a.contextElement, _b = _a.isFixed, isFixed = _b === void 0 ? false : _b, _c = _a.virtualContextElement, virtualContextElement = _c === void 0 ? true : _c, strings = _a.strings, mappings = _a.mappings, locations = _a.locations, functions = _a.functions, _d = _a.type, type = _d === void 0 ? 'flamegraph' : _d;
160
+ var x = _a.x, y = _a.y, unit = _a.unit, total = _a.total, totalUnfiltered = _a.totalUnfiltered, hoveringNodeProp = _a.hoveringNode, contextElement = _a.contextElement, _b = _a.isFixed, isFixed = _b === void 0 ? false : _b, _c = _a.virtualContextElement, virtualContextElement = _c === void 0 ? true : _c, strings = _a.strings, mappings = _a.mappings, locations = _a.locations, functions = _a.functions, _d = _a.type, type = _d === void 0 ? 'flamegraph' : _d;
158
161
  var hoveringNodeState = useAppSelector(selectHoveringNode);
159
162
  // @ts-expect-error
160
163
  var hoveringNode = useMemo(function () {
@@ -211,6 +214,6 @@ var GraphTooltip = function (_a) {
211
214
  }, [contextElement, popperProps, isShiftDown, x, y]);
212
215
  if (hoveringNode === undefined || hoveringNode == null)
213
216
  return _jsx(_Fragment, {});
214
- return isFixed ? (_jsx(GraphTooltipContent, { hoveringNode: hoveringNode, unit: unit, total: total, isFixed: isFixed, type: type })) : (_jsx("div", __assign({ ref: setPopperElement, style: styles.popper }, attributes.popper, { children: _jsx(GraphTooltipContent, { hoveringNode: hoveringNode, unit: unit, total: total, isFixed: isFixed, strings: strings, mappings: mappings, locations: locations, functions: functions, type: type }) })));
217
+ return isFixed ? (_jsx(GraphTooltipContent, { hoveringNode: hoveringNode, unit: unit, total: total, totalUnfiltered: totalUnfiltered, isFixed: isFixed, type: type })) : (_jsx("div", __assign({ ref: setPopperElement, style: styles.popper }, attributes.popper, { children: _jsx(GraphTooltipContent, { hoveringNode: hoveringNode, unit: unit, total: total, totalUnfiltered: totalUnfiltered, isFixed: isFixed, strings: strings, mappings: mappings, locations: locations, functions: functions, type: type }) })));
215
218
  };
216
219
  export default GraphTooltip;
@@ -3,6 +3,8 @@ import { Flamegraph } from '@parca/client';
3
3
  import { type NavigateFunction } from '@parca/utilities';
4
4
  interface IcicleGraphProps {
5
5
  graph: Flamegraph;
6
+ total: number;
7
+ filtered: number;
6
8
  sampleUnit: string;
7
9
  width?: number;
8
10
  curPath: string[];
@@ -32,7 +32,7 @@ import { IcicleNode, RowHeight } from './IcicleGraphNodes';
32
32
  import useColoredGraph from './useColoredGraph';
33
33
  export var IcicleGraph = memo(function IcicleGraph(_a) {
34
34
  var _b;
35
- var graph = _a.graph, width = _a.width, setCurPath = _a.setCurPath, curPath = _a.curPath, sampleUnit = _a.sampleUnit, navigateTo = _a.navigateTo;
35
+ var graph = _a.graph, total = _a.total, filtered = _a.filtered, width = _a.width, setCurPath = _a.setCurPath, curPath = _a.curPath, sampleUnit = _a.sampleUnit, navigateTo = _a.navigateTo;
36
36
  var dispatch = useAppDispatch();
37
37
  var _c = useState(0), height = _c[0], setHeight = _c[1];
38
38
  var svg = useRef(null);
@@ -45,16 +45,17 @@ export var IcicleGraph = memo(function IcicleGraph(_a) {
45
45
  setHeight(ref === null || ref === void 0 ? void 0 : ref.current.getBoundingClientRect().height);
46
46
  }
47
47
  }, [width, coloredGraph]);
48
- var total = useMemo(function () { return parseFloat(coloredGraph.total); }, [coloredGraph.total]);
49
48
  var xScale = useMemo(function () {
50
49
  if (width === undefined) {
51
50
  return function () { return 0; };
52
51
  }
53
- return scaleLinear().domain([0, total]).range([0, width]);
52
+ return scaleLinear()
53
+ .domain([0, Number(total)])
54
+ .range([0, width]);
54
55
  }, [total, width]);
55
56
  if (coloredGraph.root === undefined || width === undefined) {
56
57
  return _jsx(_Fragment, {});
57
58
  }
58
- return (_jsxs("div", __assign({ onMouseLeave: function () { return dispatch(setHoveringNode(undefined)); } }, { children: [_jsx(ColorStackLegend, { navigateTo: navigateTo, compareMode: compareMode }), _jsx(GraphTooltip, { unit: sampleUnit, total: total, contextElement: svg.current, strings: coloredGraph.stringTable, mappings: coloredGraph.mapping, locations: coloredGraph.locations, functions: coloredGraph.function }), _jsx("svg", __assign({ className: "font-robotoMono", width: width, height: height, preserveAspectRatio: "xMinYMid", ref: svg }, { children: _jsx("g", __assign({ ref: ref }, { children: _jsx("g", __assign({ transform: 'translate(0, 0)' }, { children: _jsx(IcicleNode, { x: 0, y: 0, totalWidth: width, height: RowHeight, setCurPath: setCurPath, curPath: curPath, data: coloredGraph.root, strings: coloredGraph.stringTable, mappings: coloredGraph.mapping, locations: coloredGraph.locations, functions: coloredGraph.function, total: total, xScale: xScale, path: [], level: 0, isRoot: true, searchString: currentSearchString, compareMode: compareMode }) })) })) }))] })));
59
+ return (_jsxs("div", __assign({ onMouseLeave: function () { return dispatch(setHoveringNode(undefined)); } }, { children: [_jsx(ColorStackLegend, { navigateTo: navigateTo, compareMode: compareMode }), _jsx(GraphTooltip, { unit: sampleUnit, total: total, totalUnfiltered: total + filtered, contextElement: svg.current, strings: coloredGraph.stringTable, mappings: coloredGraph.mapping, locations: coloredGraph.locations, functions: coloredGraph.function }), _jsx("svg", __assign({ className: "font-robotoMono", width: width, height: height, preserveAspectRatio: "xMinYMid", ref: svg }, { children: _jsx("g", __assign({ ref: ref }, { children: _jsx("g", __assign({ transform: 'translate(0, 0)' }, { children: _jsx(IcicleNode, { x: 0, y: 0, totalWidth: width, height: RowHeight, setCurPath: setCurPath, curPath: curPath, data: coloredGraph.root, strings: coloredGraph.stringTable, mappings: coloredGraph.mapping, locations: coloredGraph.locations, functions: coloredGraph.function, total: total, xScale: xScale, path: [], level: 0, isRoot: true, searchString: currentSearchString, compareMode: compareMode }) })) })) }))] })));
59
60
  });
60
61
  export default IcicleGraph;
@@ -5,8 +5,8 @@ export type ResizeHandler = (width: number, height: number) => void;
5
5
  interface ProfileIcicleGraphProps {
6
6
  width?: number;
7
7
  graph: Flamegraph | undefined;
8
- total: bigint;
9
- filtered: bigint;
8
+ total: number;
9
+ filtered: number;
10
10
  sampleUnit: string;
11
11
  curPath: string[] | [];
12
12
  setNewCurPath: (path: string[]) => void;
@@ -44,20 +44,20 @@ var ProfileIcicleGraph = function (_a) {
44
44
  if (graph === undefined) {
45
45
  return ['0', '0', false, '0', '0', false, '0', '0'];
46
46
  }
47
- var trimmed = BigInt(graph.trimmed);
48
- var rawTotal = total + filtered + trimmed;
47
+ var trimmed = parseInt(graph.trimmed);
48
+ var totalUnfiltered = total + filtered;
49
49
  // safeguard against division by zero
50
- var rawTotalDivisor = rawTotal > 0 ? rawTotal : BigInt(1);
50
+ var totalUnfilteredDivisor = totalUnfiltered > 0 ? totalUnfiltered : 1;
51
51
  return [
52
52
  numberFormatter.format(total),
53
- numberFormatter.format(rawTotal),
53
+ numberFormatter.format(totalUnfiltered),
54
54
  trimmed > 0,
55
55
  numberFormatter.format(trimmed),
56
- numberFormatter.format((trimmed * BigInt(100)) / rawTotalDivisor),
56
+ numberFormatter.format((trimmed * 100) / totalUnfilteredDivisor),
57
57
  filtered > 0,
58
- numberFormatter.format((total * BigInt(100)) / rawTotalDivisor),
58
+ numberFormatter.format((total * 100) / totalUnfilteredDivisor),
59
59
  ];
60
- }, [filtered, graph, total]), totalFormatted = _c[0], rawFormatted = _c[1], isTrimmed = _c[2], trimmedFormatted = _c[3], trimmedPercentage = _c[4], isFiltered = _c[5], filteredPercentage = _c[6];
60
+ }, [graph, filtered, total]), totalFormatted = _c[0], totalUnfilteredFormatted = _c[1], isTrimmed = _c[2], trimmedFormatted = _c[3], trimmedPercentage = _c[4], isFiltered = _c[5], filteredPercentage = _c[6];
61
61
  useEffect(function () {
62
62
  if (setActionButtons === undefined) {
63
63
  return;
@@ -66,11 +66,11 @@ var ProfileIcicleGraph = function (_a) {
66
66
  }, [setNewCurPath, curPath, setActionButtons]);
67
67
  if (graph === undefined)
68
68
  return _jsx("div", { children: "no data..." });
69
- if (total === BigInt(0) && !loading)
69
+ if (total === 0 && !loading)
70
70
  return _jsx(_Fragment, { children: "Profile has no samples" });
71
71
  if (isTrimmed) {
72
72
  console.info("Trimmed ".concat(trimmedFormatted, " (").concat(trimmedPercentage, "%) too small values."));
73
73
  }
74
- return (_jsxs("div", __assign({ className: "relative" }, { children: [compareMode && _jsx(DiffLegend, {}), _jsx("div", __assign({ ref: ref }, { children: _jsx(IcicleGraph, { width: dimensions === null || dimensions === void 0 ? void 0 : dimensions.width, graph: graph, curPath: curPath, setCurPath: setNewCurPath, sampleUnit: sampleUnit, navigateTo: navigateTo }) })), _jsxs("p", __assign({ className: "my-2 text-xs" }, { children: ["Showing ", totalFormatted, ' ', isFiltered ? (_jsxs("span", { children: ["(", filteredPercentage, "%) filtered of ", rawFormatted, ' '] })) : (_jsx(_Fragment, {})), "values.", ' '] }))] })));
74
+ return (_jsxs("div", __assign({ className: "relative" }, { children: [compareMode && _jsx(DiffLegend, {}), _jsx("div", __assign({ ref: ref }, { children: _jsx(IcicleGraph, { width: dimensions === null || dimensions === void 0 ? void 0 : dimensions.width, graph: graph, total: total, filtered: filtered, curPath: curPath, setCurPath: setNewCurPath, sampleUnit: sampleUnit, navigateTo: navigateTo }) })), _jsxs("p", __assign({ className: "my-2 text-xs" }, { children: ["Showing ", totalFormatted, ' ', isFiltered ? (_jsxs("span", { children: ["(", filteredPercentage, "%) filtered of ", totalUnfilteredFormatted, ' '] })) : (_jsx(_Fragment, {})), "values.", ' '] }))] })));
75
75
  };
76
76
  export default ProfileIcicleGraph;
@@ -209,7 +209,7 @@ export var ProfileView = function (_a) {
209
209
  return (flamegraphData === null || flamegraphData === void 0 ? void 0 : flamegraphData.data) != null ? (_jsx(ConditionalWrapper, __assign({ condition: (perf === null || perf === void 0 ? void 0 : perf.onRender) != null, WrapperComponent: Profiler, wrapperProps: {
210
210
  id: 'icicleGraph',
211
211
  onRender: perf === null || perf === void 0 ? void 0 : perf.onRender,
212
- } }, { children: _jsx(ProfileIcicleGraph, { curPath: curPath, setNewCurPath: setNewCurPath, graph: flamegraphData.data, total: (_b = flamegraphData === null || flamegraphData === void 0 ? void 0 : flamegraphData.total) !== null && _b !== void 0 ? _b : BigInt(0), filtered: (_c = flamegraphData === null || flamegraphData === void 0 ? void 0 : flamegraphData.filtered) !== null && _c !== void 0 ? _c : BigInt(0), sampleUnit: sampleUnit, onContainerResize: onFlamegraphContainerResize, navigateTo: navigateTo, loading: flamegraphData.loading, setActionButtons: setActionButtons }) }))) : (_jsx(_Fragment, { children: " " }));
212
+ } }, { children: _jsx(ProfileIcicleGraph, { curPath: curPath, setNewCurPath: setNewCurPath, graph: flamegraphData.data, total: (_b = Number(flamegraphData.total)) !== null && _b !== void 0 ? _b : 0, filtered: (_c = Number(flamegraphData === null || flamegraphData === void 0 ? void 0 : flamegraphData.filtered)) !== null && _c !== void 0 ? _c : 0, sampleUnit: sampleUnit, onContainerResize: onFlamegraphContainerResize, navigateTo: navigateTo, loading: flamegraphData.loading, setActionButtons: setActionButtons }) }))) : (_jsx(_Fragment, { children: " " }));
213
213
  }
214
214
  case 'callgraph': {
215
215
  return (callgraphData === null || callgraphData === void 0 ? void 0 : callgraphData.data) !== undefined &&
package/package.json CHANGED
@@ -1,15 +1,14 @@
1
1
  {
2
2
  "name": "@parca/profile",
3
- "version": "0.16.145",
3
+ "version": "0.16.147",
4
4
  "description": "Profile viewing libraries",
5
5
  "dependencies": {
6
6
  "@parca/client": "^0.16.69",
7
- "@parca/components": "^0.16.119",
7
+ "@parca/components": "^0.16.120",
8
8
  "@parca/dynamicsize": "^0.16.54",
9
- "@parca/functions": "^0.16.70",
10
- "@parca/hooks": "^0.0.3",
9
+ "@parca/hooks": "^0.0.2",
11
10
  "@parca/parser": "^0.16.55",
12
- "@parca/store": "^0.16.69",
11
+ "@parca/store": "^0.16.70",
13
12
  "@parca/utilities": "^0.0.3",
14
13
  "@types/react-beautiful-dnd": "^13.1.3",
15
14
  "d3": "7.8.2",
@@ -47,5 +46,5 @@
47
46
  "access": "public",
48
47
  "registry": "https://registry.npmjs.org/"
49
48
  },
50
- "gitHead": "472dedb7be9a8b5eaee182d4fe42bf0ab2cb03d0"
49
+ "gitHead": "07c1df891a73f46002413ddb95d7031411d8d249"
51
50
  }
@@ -149,6 +149,7 @@ const Callgraph = ({data, svgString, sampleUnit, width}: Props): JSX.Element =>
149
149
  type="callgraph"
150
150
  unit={sampleUnit}
151
151
  total={parseInt(data.cumulative)}
152
+ totalUnfiltered={parseInt(data.cumulative)}
152
153
  contextElement={containerRef.current}
153
154
  />
154
155
  )}
@@ -55,6 +55,7 @@ interface GraphTooltipProps {
55
55
  y?: number;
56
56
  unit: string;
57
57
  total: number;
58
+ totalUnfiltered: number;
58
59
  hoveringNode?: HoveringNode;
59
60
  contextElement: Element | null;
60
61
  isFixed?: boolean;
@@ -244,6 +245,7 @@ export const GraphTooltipContent = ({
244
245
  hoveringNode,
245
246
  unit,
246
247
  total,
248
+ totalUnfiltered,
247
249
  isFixed,
248
250
  strings,
249
251
  mappings,
@@ -254,6 +256,7 @@ export const GraphTooltipContent = ({
254
256
  hoveringNode: HoveringNode;
255
257
  unit: string;
256
258
  total: number;
259
+ totalUnfiltered: number;
257
260
  isFixed: boolean;
258
261
  strings?: string[];
259
262
  mappings?: Mapping[];
@@ -282,8 +285,12 @@ export const GraphTooltipContent = ({
282
285
  const diffText = `${diffValueText} (${diffPercentageText})`;
283
286
 
284
287
  const getTextForCumulative = (hoveringNodeCumulative: number): string => {
285
- return `${valueFormatter(hoveringNodeCumulative, unit, 2)} (
286
- ${((hoveringNodeCumulative * 100) / total).toFixed(2)}%)`;
288
+ const filtered =
289
+ totalUnfiltered > total
290
+ ? ` / ${((hoveringNodeCumulative * 100) / total).toFixed(2)}% of filtered`
291
+ : '';
292
+ return `${valueFormatter(hoveringNodeCumulative, unit, 2)}
293
+ (${((hoveringNodeCumulative * 100) / totalUnfiltered).toFixed(2)}%${filtered})`;
287
294
  };
288
295
 
289
296
  return (
@@ -377,6 +384,7 @@ const GraphTooltip = ({
377
384
  y,
378
385
  unit,
379
386
  total,
387
+ totalUnfiltered,
380
388
  hoveringNode: hoveringNodeProp,
381
389
  contextElement,
382
390
  isFixed = false,
@@ -468,6 +476,7 @@ const GraphTooltip = ({
468
476
  hoveringNode={hoveringNode}
469
477
  unit={unit}
470
478
  total={total}
479
+ totalUnfiltered={totalUnfiltered}
471
480
  isFixed={isFixed}
472
481
  type={type}
473
482
  />
@@ -477,6 +486,7 @@ const GraphTooltip = ({
477
486
  hoveringNode={hoveringNode}
478
487
  unit={unit}
479
488
  total={total}
489
+ totalUnfiltered={totalUnfiltered}
480
490
  isFixed={isFixed}
481
491
  strings={strings}
482
492
  mappings={mappings}
@@ -26,6 +26,8 @@ import useColoredGraph from './useColoredGraph';
26
26
 
27
27
  interface IcicleGraphProps {
28
28
  graph: Flamegraph;
29
+ total: number;
30
+ filtered: number;
29
31
  sampleUnit: string;
30
32
  width?: number;
31
33
  curPath: string[];
@@ -35,6 +37,8 @@ interface IcicleGraphProps {
35
37
 
36
38
  export const IcicleGraph = memo(function IcicleGraph({
37
39
  graph,
40
+ total,
41
+ filtered,
38
42
  width,
39
43
  setCurPath,
40
44
  curPath,
@@ -57,12 +61,13 @@ export const IcicleGraph = memo(function IcicleGraph({
57
61
  }
58
62
  }, [width, coloredGraph]);
59
63
 
60
- const total = useMemo(() => parseFloat(coloredGraph.total), [coloredGraph.total]);
61
64
  const xScale = useMemo(() => {
62
65
  if (width === undefined) {
63
66
  return () => 0;
64
67
  }
65
- return scaleLinear().domain([0, total]).range([0, width]);
68
+ return scaleLinear()
69
+ .domain([0, Number(total)])
70
+ .range([0, width]);
66
71
  }, [total, width]);
67
72
 
68
73
  if (coloredGraph.root === undefined || width === undefined) {
@@ -75,6 +80,7 @@ export const IcicleGraph = memo(function IcicleGraph({
75
80
  <GraphTooltip
76
81
  unit={sampleUnit}
77
82
  total={total}
83
+ totalUnfiltered={total + filtered}
78
84
  contextElement={svg.current}
79
85
  strings={coloredGraph.stringTable}
80
86
  mappings={coloredGraph.mapping}
@@ -28,8 +28,8 @@ export type ResizeHandler = (width: number, height: number) => void;
28
28
  interface ProfileIcicleGraphProps {
29
29
  width?: number;
30
30
  graph: Flamegraph | undefined;
31
- total: bigint;
32
- filtered: bigint;
31
+ total: number;
32
+ filtered: number;
33
33
  sampleUnit: string;
34
34
  curPath: string[] | [];
35
35
  setNewCurPath: (path: string[]) => void;
@@ -64,7 +64,7 @@ const ProfileIcicleGraph = ({
64
64
 
65
65
  const [
66
66
  totalFormatted,
67
- rawFormatted,
67
+ totalUnfilteredFormatted,
68
68
  isTrimmed,
69
69
  trimmedFormatted,
70
70
  trimmedPercentage,
@@ -75,23 +75,22 @@ const ProfileIcicleGraph = ({
75
75
  return ['0', '0', false, '0', '0', false, '0', '0'];
76
76
  }
77
77
 
78
- const trimmed = BigInt(graph.trimmed);
79
-
80
- const rawTotal = total + filtered + trimmed;
78
+ const trimmed = parseInt(graph.trimmed);
81
79
 
80
+ const totalUnfiltered = total + filtered;
82
81
  // safeguard against division by zero
83
- const rawTotalDivisor = rawTotal > 0 ? rawTotal : BigInt(1);
82
+ const totalUnfilteredDivisor = totalUnfiltered > 0 ? totalUnfiltered : 1;
84
83
 
85
84
  return [
86
85
  numberFormatter.format(total),
87
- numberFormatter.format(rawTotal),
86
+ numberFormatter.format(totalUnfiltered),
88
87
  trimmed > 0,
89
88
  numberFormatter.format(trimmed),
90
- numberFormatter.format((trimmed * BigInt(100)) / rawTotalDivisor),
89
+ numberFormatter.format((trimmed * 100) / totalUnfilteredDivisor),
91
90
  filtered > 0,
92
- numberFormatter.format((total * BigInt(100)) / rawTotalDivisor),
91
+ numberFormatter.format((total * 100) / totalUnfilteredDivisor),
93
92
  ];
94
- }, [filtered, graph, total]);
93
+ }, [graph, filtered, total]);
95
94
 
96
95
  useEffect(() => {
97
96
  if (setActionButtons === undefined) {
@@ -114,7 +113,7 @@ const ProfileIcicleGraph = ({
114
113
 
115
114
  if (graph === undefined) return <div>no data...</div>;
116
115
 
117
- if (total === BigInt(0) && !loading) return <>Profile has no samples</>;
116
+ if (total === 0 && !loading) return <>Profile has no samples</>;
118
117
 
119
118
  if (isTrimmed) {
120
119
  console.info(`Trimmed ${trimmedFormatted} (${trimmedPercentage}%) too small values.`);
@@ -127,6 +126,8 @@ const ProfileIcicleGraph = ({
127
126
  <IcicleGraph
128
127
  width={dimensions?.width}
129
128
  graph={graph}
129
+ total={total}
130
+ filtered={filtered}
130
131
  curPath={curPath}
131
132
  setCurPath={setNewCurPath}
132
133
  sampleUnit={sampleUnit}
@@ -137,7 +138,7 @@ const ProfileIcicleGraph = ({
137
138
  Showing {totalFormatted}{' '}
138
139
  {isFiltered ? (
139
140
  <span>
140
- ({filteredPercentage}%) filtered of {rawFormatted}{' '}
141
+ ({filteredPercentage}%) filtered of {totalUnfilteredFormatted}{' '}
141
142
  </span>
142
143
  ) : (
143
144
  <></>
@@ -235,8 +235,8 @@ export const ProfileView = ({
235
235
  curPath={curPath}
236
236
  setNewCurPath={setNewCurPath}
237
237
  graph={flamegraphData.data}
238
- total={flamegraphData?.total ?? BigInt(0)}
239
- filtered={flamegraphData?.filtered ?? BigInt(0)}
238
+ total={Number(flamegraphData.total) ?? 0}
239
+ filtered={Number(flamegraphData?.filtered) ?? 0}
240
240
  sampleUnit={sampleUnit}
241
241
  onContainerResize={onFlamegraphContainerResize}
242
242
  navigateTo={navigateTo}