@parca/profile 0.19.153 → 0.19.155
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 +8 -0
- package/dist/GraphTooltipArrow/Content.d.ts.map +1 -1
- package/dist/GraphTooltipArrow/Content.js +80 -54
- package/dist/GraphTooltipArrow/gpuFrameDescriptions.d.ts +3 -0
- package/dist/GraphTooltipArrow/gpuFrameDescriptions.d.ts.map +1 -1
- package/dist/GraphTooltipArrow/gpuFrameDescriptions.js +63 -20
- package/dist/GraphTooltipArrow/useGraphTooltipMetaInfo/index.d.ts.map +1 -1
- package/dist/GraphTooltipArrow/useGraphTooltipMetaInfo/index.js +2 -11
- package/dist/ProfileFlameGraph/FlameGraphArrow/utils.d.ts +1 -0
- package/dist/ProfileFlameGraph/FlameGraphArrow/utils.d.ts.map +1 -1
- package/dist/ProfileFlameGraph/FlameGraphArrow/utils.js +5 -2
- package/dist/ProfileTypeSelector/index.d.ts.map +1 -1
- package/dist/ProfileTypeSelector/index.js +6 -4
- package/package.json +2 -2
- package/src/GraphTooltipArrow/Content.tsx +32 -7
- package/src/GraphTooltipArrow/gpuFrameDescriptions.test.ts +42 -1
- package/src/GraphTooltipArrow/gpuFrameDescriptions.ts +47 -18
- package/src/GraphTooltipArrow/useGraphTooltipMetaInfo/index.ts +2 -9
- package/src/ProfileFlameGraph/FlameGraphArrow/utils.ts +6 -2
- package/src/ProfileTypeSelector/index.tsx +6 -4
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.19.155](https://github.com/parca-dev/parca/compare/@parca/profile@0.19.154...@parca/profile@0.19.155) (2026-06-09)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @parca/profile
|
|
9
|
+
|
|
10
|
+
## [0.19.154](https://github.com/parca-dev/parca/compare/@parca/profile@0.19.153...@parca/profile@0.19.154) (2026-05-28)
|
|
11
|
+
|
|
12
|
+
**Note:** Version bump only for package @parca/profile
|
|
13
|
+
|
|
6
14
|
## [0.19.153](https://github.com/parca-dev/parca/compare/@parca/profile@0.19.152...@parca/profile@0.19.153) (2026-05-21)
|
|
7
15
|
|
|
8
16
|
**Note:** Version bump only for package @parca/profile
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Content.d.ts","sourceRoot":"","sources":["../../src/GraphTooltipArrow/Content.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAC,KAAK,EAAC,MAAM,mBAAmB,CAAC;AAGxC,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"Content.d.ts","sourceRoot":"","sources":["../../src/GraphTooltipArrow/Content.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAC,KAAK,EAAC,MAAM,mBAAmB,CAAC;AAGxC,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;AAW1C,UAAU,6BAA6B;IACrC,KAAK,EAAE,KAAK,CAAC;IACb,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,EAAE,MAAM,CAAC;IACxB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,eAAe,EAAE,OAAO,CAAC;IACzB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAMD,QAAA,MAAM,wBAAwB,GAAI,8FAU/B,6BAA6B,KAAG,KAAK,CAAC,GAAG,CAAC,OAgG5C,CAAC;AAyKF,eAAe,wBAAwB,CAAC"}
|
|
@@ -16,9 +16,10 @@ import React from 'react';
|
|
|
16
16
|
import { Icon } from '@iconify/react';
|
|
17
17
|
import { useParcaContext } from '@parca/components';
|
|
18
18
|
import { formatDateTimeDownToMS, getLastItem } from '@parca/utilities';
|
|
19
|
+
import { getLabelPairs } from '../ProfileFlameGraph/FlameGraphArrow/utils';
|
|
19
20
|
import { hexifyAddress, truncateString, truncateStringReverse } from '../utils';
|
|
20
21
|
import { ExpandOnHover } from './ExpandOnHoverValue';
|
|
21
|
-
import {
|
|
22
|
+
import { gpuFrameInfosFromLabels } from './gpuFrameDescriptions';
|
|
22
23
|
import { openInNewTab } from './openInNewTab';
|
|
23
24
|
import { useGraphTooltip } from './useGraphTooltip';
|
|
24
25
|
import { useGraphTooltipMetaInfo } from './useGraphTooltipMetaInfo';
|
|
@@ -67,7 +68,7 @@ var GraphTooltipArrowContent = function GraphTooltipArrowContent(_ref) {
|
|
|
67
68
|
diffText = graphTooltipData.diffText,
|
|
68
69
|
diff = graphTooltipData.diff,
|
|
69
70
|
rowNumber = graphTooltipData.row;
|
|
70
|
-
var
|
|
71
|
+
var gpuInfos = gpuFrameInfosFromLabels(getLabelPairs(table, rowNumber));
|
|
71
72
|
|
|
72
73
|
// Outer card gains a subtle ring when frozen, matching the design's
|
|
73
74
|
// `.is-frozen` treatment.
|
|
@@ -129,8 +130,14 @@ var GraphTooltipArrowContent = function GraphTooltipArrowContent(_ref) {
|
|
|
129
130
|
})
|
|
130
131
|
})]
|
|
131
132
|
})
|
|
132
|
-
}),
|
|
133
|
-
|
|
133
|
+
}), gpuInfos.map(function (info, i) {
|
|
134
|
+
return /*#__PURE__*/_jsx(GpuDescriptionBlock, {
|
|
135
|
+
info: info
|
|
136
|
+
// When both a SASS and a stall block are shown, keep the tooltip
|
|
137
|
+
// compact by trimming the (typically longer) stall description.
|
|
138
|
+
,
|
|
139
|
+
maxSentences: gpuInfos.length > 1 && info.kind === 'stall' ? 2 : undefined
|
|
140
|
+
}, i);
|
|
134
141
|
}), /*#__PURE__*/_jsx(ShortcutFooter, {
|
|
135
142
|
frozen: frozen
|
|
136
143
|
})]
|
|
@@ -138,96 +145,115 @@ var GraphTooltipArrowContent = function GraphTooltipArrowContent(_ref) {
|
|
|
138
145
|
})
|
|
139
146
|
});
|
|
140
147
|
};
|
|
148
|
+
|
|
149
|
+
// Trims a description to at most `max` sentences, appending an ellipsis when
|
|
150
|
+
// anything was dropped.
|
|
151
|
+
var truncateToSentences = function truncateToSentences(text, max) {
|
|
152
|
+
var sentences = text.match(/[^.!?]+[.!?]+(\s|$)|[^.!?]+$/g);
|
|
153
|
+
if (sentences === null || sentences.length <= max) return text;
|
|
154
|
+
return "".concat(sentences.slice(0, max).join('').trimEnd(), " \u2026");
|
|
155
|
+
};
|
|
141
156
|
var GpuDescriptionBlock = function GpuDescriptionBlock(t0) {
|
|
142
|
-
var $ = _c(
|
|
143
|
-
var info = t0.info
|
|
157
|
+
var $ = _c(19);
|
|
158
|
+
var info = t0.info,
|
|
159
|
+
maxSentences = t0.maxSentences;
|
|
144
160
|
var chipPrefix = info.kind === "stall" ? "Stall reason" : "SASS instruction";
|
|
145
161
|
var t1;
|
|
146
|
-
if ($[0] !==
|
|
147
|
-
t1 =
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
});
|
|
151
|
-
$[0] = chipPrefix;
|
|
152
|
-
$[1] = info.entry.reasonLabel;
|
|
162
|
+
if ($[0] !== info.entry.description || $[1] !== maxSentences) {
|
|
163
|
+
t1 = maxSentences === undefined ? info.entry.description : truncateToSentences(info.entry.description, maxSentences);
|
|
164
|
+
$[0] = info.entry.description;
|
|
165
|
+
$[1] = maxSentences;
|
|
153
166
|
$[2] = t1;
|
|
154
167
|
} else {
|
|
155
168
|
t1 = $[2];
|
|
156
169
|
}
|
|
170
|
+
var description = t1;
|
|
157
171
|
var t2;
|
|
158
|
-
if ($[3]
|
|
159
|
-
t2 = /*#__PURE__*/
|
|
172
|
+
if ($[3] !== chipPrefix || $[4] !== info.entry.reasonLabel) {
|
|
173
|
+
t2 = /*#__PURE__*/_jsxs("div", {
|
|
174
|
+
className: "mb-2 text-xs font-semibold text-gray-700 dark:text-gray-200",
|
|
175
|
+
children: [chipPrefix, " \xB7 ", info.entry.reasonLabel]
|
|
176
|
+
});
|
|
177
|
+
$[3] = chipPrefix;
|
|
178
|
+
$[4] = info.entry.reasonLabel;
|
|
179
|
+
$[5] = t2;
|
|
180
|
+
} else {
|
|
181
|
+
t2 = $[5];
|
|
182
|
+
}
|
|
183
|
+
var t3;
|
|
184
|
+
if ($[6] === Symbol["for"]("react.memo_cache_sentinel")) {
|
|
185
|
+
t3 = /*#__PURE__*/_jsx("div", {
|
|
160
186
|
className: "font-mono text-[10px] uppercase tracking-wider text-gray-500 dark:text-gray-400",
|
|
161
187
|
children: "Description"
|
|
162
188
|
});
|
|
163
|
-
$[
|
|
189
|
+
$[6] = t3;
|
|
164
190
|
} else {
|
|
165
|
-
|
|
191
|
+
t3 = $[6];
|
|
166
192
|
}
|
|
167
|
-
var
|
|
168
|
-
if ($[
|
|
169
|
-
|
|
193
|
+
var t4;
|
|
194
|
+
if ($[7] !== description) {
|
|
195
|
+
t4 = /*#__PURE__*/_jsx("p", {
|
|
170
196
|
className: "mt-1 text-xs leading-relaxed text-gray-600 dark:text-gray-300",
|
|
171
|
-
children:
|
|
197
|
+
children: description
|
|
172
198
|
});
|
|
173
|
-
$[
|
|
174
|
-
$[
|
|
199
|
+
$[7] = description;
|
|
200
|
+
$[8] = t4;
|
|
175
201
|
} else {
|
|
176
|
-
|
|
202
|
+
t4 = $[8];
|
|
177
203
|
}
|
|
178
|
-
var
|
|
179
|
-
if ($[
|
|
180
|
-
|
|
204
|
+
var t5;
|
|
205
|
+
if ($[9] !== info.sourceUrl) {
|
|
206
|
+
t5 = function t5(e) {
|
|
181
207
|
e.preventDefault();
|
|
182
208
|
e.stopPropagation();
|
|
183
209
|
openInNewTab(info.sourceUrl);
|
|
184
210
|
};
|
|
185
|
-
$[
|
|
186
|
-
$[
|
|
211
|
+
$[9] = info.sourceUrl;
|
|
212
|
+
$[10] = t5;
|
|
187
213
|
} else {
|
|
188
|
-
|
|
214
|
+
t5 = $[10];
|
|
189
215
|
}
|
|
190
|
-
var
|
|
191
|
-
if ($[
|
|
192
|
-
|
|
216
|
+
var t6;
|
|
217
|
+
if ($[11] === Symbol["for"]("react.memo_cache_sentinel")) {
|
|
218
|
+
t6 = /*#__PURE__*/_jsx(Icon, {
|
|
193
219
|
icon: "iconoir:open-new-window",
|
|
194
220
|
className: "opacity-80",
|
|
195
221
|
width: 11,
|
|
196
222
|
height: 11
|
|
197
223
|
});
|
|
198
|
-
$[
|
|
224
|
+
$[11] = t6;
|
|
199
225
|
} else {
|
|
200
|
-
|
|
226
|
+
t6 = $[11];
|
|
201
227
|
}
|
|
202
|
-
var
|
|
203
|
-
if ($[
|
|
204
|
-
|
|
228
|
+
var t7;
|
|
229
|
+
if ($[12] !== info.sourceLabel || $[13] !== t5) {
|
|
230
|
+
t7 = /*#__PURE__*/_jsxs("button", {
|
|
205
231
|
type: "button",
|
|
206
|
-
onClick:
|
|
232
|
+
onClick: t5,
|
|
207
233
|
title: info.sourceLabel,
|
|
208
234
|
className: "mt-2 inline-flex cursor-pointer items-center gap-1 self-start text-[11px] text-indigo-600 hover:underline dark:text-indigo-400",
|
|
209
|
-
children: ["Docs",
|
|
235
|
+
children: ["Docs", t6]
|
|
210
236
|
});
|
|
211
|
-
$[
|
|
212
|
-
$[
|
|
213
|
-
$[
|
|
237
|
+
$[12] = info.sourceLabel;
|
|
238
|
+
$[13] = t5;
|
|
239
|
+
$[14] = t7;
|
|
214
240
|
} else {
|
|
215
|
-
|
|
241
|
+
t7 = $[14];
|
|
216
242
|
}
|
|
217
|
-
var
|
|
218
|
-
if ($[
|
|
219
|
-
|
|
243
|
+
var t8;
|
|
244
|
+
if ($[15] !== t2 || $[16] !== t4 || $[17] !== t7) {
|
|
245
|
+
t8 = /*#__PURE__*/_jsxs("div", {
|
|
220
246
|
className: "mx-2 mt-3 border-t border-gray-200 pt-3 dark:border-gray-700",
|
|
221
|
-
children: [
|
|
247
|
+
children: [t2, t3, t4, t7]
|
|
222
248
|
});
|
|
223
|
-
$[
|
|
224
|
-
$[
|
|
225
|
-
$[
|
|
226
|
-
$[
|
|
249
|
+
$[15] = t2;
|
|
250
|
+
$[16] = t4;
|
|
251
|
+
$[17] = t7;
|
|
252
|
+
$[18] = t8;
|
|
227
253
|
} else {
|
|
228
|
-
|
|
254
|
+
t8 = $[18];
|
|
229
255
|
}
|
|
230
|
-
return
|
|
256
|
+
return t8;
|
|
231
257
|
};
|
|
232
258
|
var ShortcutFooter = function ShortcutFooter(t0) {
|
|
233
259
|
var $ = _c(14);
|
|
@@ -24,5 +24,8 @@ export type GpuFrameInfo = {
|
|
|
24
24
|
sourceLabel: string;
|
|
25
25
|
sourceUrl: string;
|
|
26
26
|
};
|
|
27
|
+
export declare const CUDA_SASS_INSTRUCTION_LABEL = "cuda_sass_instruction";
|
|
28
|
+
export declare const CUDA_STALL_REASON_LABEL = "cuda_stall_reason";
|
|
27
29
|
export declare function gpuFrameInfo(name: string): GpuFrameInfo | undefined;
|
|
30
|
+
export declare function gpuFrameInfosFromLabels(labelPairs: Array<[string, string]>): GpuFrameInfo[];
|
|
28
31
|
//# sourceMappingURL=gpuFrameDescriptions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gpuFrameDescriptions.d.ts","sourceRoot":"","sources":["../../src/GraphTooltipArrow/gpuFrameDescriptions.ts"],"names":[],"mappings":"AAkCA,eAAO,MAAM,iBAAiB,gBAAgB,CAAC;AAC/C,eAAO,MAAM,gBAAgB,wFAC0D,CAAC;AACxF,eAAO,MAAM,eAAe,sGACyE,CAAC;AAEtG,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,SAAS;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAGD,eAAO,MAAM,6BAA6B,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAkRnE,CAAC;AAGF,eAAO,MAAM,yBAAyB,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CA4LhE,CAAC;AAGF,MAAM,MAAM,YAAY,GACpB;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,SAAS,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAC,GACxE;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,UAAU,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"gpuFrameDescriptions.d.ts","sourceRoot":"","sources":["../../src/GraphTooltipArrow/gpuFrameDescriptions.ts"],"names":[],"mappings":"AAkCA,eAAO,MAAM,iBAAiB,gBAAgB,CAAC;AAC/C,eAAO,MAAM,gBAAgB,wFAC0D,CAAC;AACxF,eAAO,MAAM,eAAe,sGACyE,CAAC;AAEtG,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,SAAS;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAGD,eAAO,MAAM,6BAA6B,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAkRnE,CAAC;AAGF,eAAO,MAAM,yBAAyB,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CA4LhE,CAAC;AAGF,MAAM,MAAM,YAAY,GACpB;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,SAAS,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAC,GACxE;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,UAAU,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAC,CAAC;AAY/E,eAAO,MAAM,2BAA2B,0BAA0B,CAAC;AACnE,eAAO,MAAM,uBAAuB,sBAAsB,CAAC;AA4B3D,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAEnE;AAKD,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,YAAY,EAAE,CAa3F"}
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
|
|
2
|
+
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
3
|
+
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
4
|
+
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
5
|
+
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
6
|
+
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
|
|
1
7
|
// Copyright 2022 The Parca Authors
|
|
2
8
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
3
9
|
// you may not use this file except in compliance with the License.
|
|
@@ -817,29 +823,66 @@ function stallSourceUrl(name) {
|
|
|
817
823
|
return "".concat(STALL_SOURCE_URL, ":~:text=").concat(encodeURIComponent(name));
|
|
818
824
|
}
|
|
819
825
|
|
|
826
|
+
// Node label keys under which GPU PC-sampling values now arrive. The SASS
|
|
827
|
+
// mnemonic and warp stall reason used to be the leaf frame's function name;
|
|
828
|
+
// they are now carried as node labels.
|
|
829
|
+
export var CUDA_SASS_INSTRUCTION_LABEL = 'cuda_sass_instruction';
|
|
830
|
+
export var CUDA_STALL_REASON_LABEL = 'cuda_stall_reason';
|
|
831
|
+
function sassInfo(name) {
|
|
832
|
+
var _sass$sourceUrl;
|
|
833
|
+
if (name === '') return undefined;
|
|
834
|
+
var sass = SASS_INSTRUCTION_DESCRIPTIONS[name];
|
|
835
|
+
if (sass === undefined) return undefined;
|
|
836
|
+
return {
|
|
837
|
+
kind: 'sass',
|
|
838
|
+
entry: sass,
|
|
839
|
+
sourceLabel: NVIDIA_DOCS_LABEL,
|
|
840
|
+
sourceUrl: (_sass$sourceUrl = sass.sourceUrl) !== null && _sass$sourceUrl !== void 0 ? _sass$sourceUrl : SASS_SOURCE_URL
|
|
841
|
+
};
|
|
842
|
+
}
|
|
843
|
+
function stallInfo(name) {
|
|
844
|
+
var _stall$sourceUrl;
|
|
845
|
+
if (name === '') return undefined;
|
|
846
|
+
var stall = STALL_REASON_DESCRIPTIONS[name];
|
|
847
|
+
if (stall === undefined) return undefined;
|
|
848
|
+
return {
|
|
849
|
+
kind: 'stall',
|
|
850
|
+
entry: stall,
|
|
851
|
+
sourceLabel: NVIDIA_DOCS_LABEL,
|
|
852
|
+
sourceUrl: (_stall$sourceUrl = stall.sourceUrl) !== null && _stall$sourceUrl !== void 0 ? _stall$sourceUrl : stallSourceUrl(name)
|
|
853
|
+
};
|
|
854
|
+
}
|
|
855
|
+
|
|
820
856
|
// Resolves a frame name to its GPU info, or undefined if not a known SASS
|
|
821
857
|
// mnemonic or PC-sampling reason. Both tables are exact-match lookups.
|
|
822
858
|
export function gpuFrameInfo(name) {
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
859
|
+
var _sassInfo;
|
|
860
|
+
return (_sassInfo = sassInfo(name)) !== null && _sassInfo !== void 0 ? _sassInfo : stallInfo(name);
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
// Resolves GPU info from a node's labels. A node may carry both a SASS
|
|
864
|
+
// instruction and a stall reason label, so this returns an array (SASS first,
|
|
865
|
+
// then stall) of the entries that matched a known description.
|
|
866
|
+
export function gpuFrameInfosFromLabels(labelPairs) {
|
|
867
|
+
var _labelPairs$find, _labelPairs$find2;
|
|
868
|
+
var infos = [];
|
|
869
|
+
var sassValue = (_labelPairs$find = labelPairs.find(function (_ref) {
|
|
870
|
+
var _ref2 = _slicedToArray(_ref, 1),
|
|
871
|
+
key = _ref2[0];
|
|
872
|
+
return key === CUDA_SASS_INSTRUCTION_LABEL;
|
|
873
|
+
})) === null || _labelPairs$find === void 0 ? void 0 : _labelPairs$find[1];
|
|
874
|
+
var stallValue = (_labelPairs$find2 = labelPairs.find(function (_ref3) {
|
|
875
|
+
var _ref4 = _slicedToArray(_ref3, 1),
|
|
876
|
+
key = _ref4[0];
|
|
877
|
+
return key === CUDA_STALL_REASON_LABEL;
|
|
878
|
+
})) === null || _labelPairs$find2 === void 0 ? void 0 : _labelPairs$find2[1];
|
|
879
|
+
if (sassValue !== undefined) {
|
|
880
|
+
var info = sassInfo(sassValue);
|
|
881
|
+
if (info !== undefined) infos.push(info);
|
|
833
882
|
}
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
return {
|
|
838
|
-
kind: 'stall',
|
|
839
|
-
entry: stall,
|
|
840
|
-
sourceLabel: NVIDIA_DOCS_LABEL,
|
|
841
|
-
sourceUrl: (_stall$sourceUrl = stall.sourceUrl) !== null && _stall$sourceUrl !== void 0 ? _stall$sourceUrl : stallSourceUrl(name)
|
|
842
|
-
};
|
|
883
|
+
if (stallValue !== undefined) {
|
|
884
|
+
var _info = stallInfo(stallValue);
|
|
885
|
+
if (_info !== undefined) infos.push(_info);
|
|
843
886
|
}
|
|
844
|
-
return
|
|
887
|
+
return infos;
|
|
845
888
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/GraphTooltipArrow/useGraphTooltipMetaInfo/index.ts"],"names":[],"mappings":"AAaA,OAAO,EAAC,KAAK,EAAC,MAAM,mBAAmB,CAAC;AAwBxC,UAAU,KAAK;IACb,KAAK,EAAE,KAAK,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb;AAED,UAAU,wBAAwB;IAChC,UAAU,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACpC,gBAAgB,EAAE,MAAM,CAAC;IACzB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,eAAO,MAAM,uBAAuB,GAAI,gBAAc,KAAK,KAAG,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/GraphTooltipArrow/useGraphTooltipMetaInfo/index.ts"],"names":[],"mappings":"AAaA,OAAO,EAAC,KAAK,EAAC,MAAM,mBAAmB,CAAC;AAwBxC,UAAU,KAAK;IACb,KAAK,EAAE,KAAK,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb;AAED,UAAU,wBAAwB;IAChC,UAAU,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACpC,gBAAgB,EAAE,MAAM,CAAC;IACzB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,eAAO,MAAM,uBAAuB,GAAI,gBAAc,KAAK,KAAG,wBAkF7D,CAAC"}
|
|
@@ -21,7 +21,7 @@ import { useQueryState } from 'nuqs';
|
|
|
21
21
|
import { QueryRequest_ReportType } from '@parca/client';
|
|
22
22
|
import { useParcaContext } from '@parca/components';
|
|
23
23
|
import { FIELD_FUNCTION_FILE_NAME, FIELD_FUNCTION_START_LINE, FIELD_FUNCTION_SYSTEM_NAME, FIELD_INLINED, FIELD_LOCATION_ADDRESS, FIELD_LOCATION_LINE, FIELD_MAPPING_BUILD_ID, FIELD_MAPPING_FILE, FIELD_TIMESTAMP } from '../../ProfileFlameGraph/FlameGraphArrow';
|
|
24
|
-
import { arrowToString } from '../../ProfileFlameGraph/FlameGraphArrow/utils';
|
|
24
|
+
import { arrowToString, getLabelPairs } from '../../ProfileFlameGraph/FlameGraphArrow/utils';
|
|
25
25
|
import { useProfileViewContext } from '../../ProfileView/context/ProfileViewContext';
|
|
26
26
|
import { stringParam } from '../../hooks/urlParsers';
|
|
27
27
|
import { useDashboardItems } from '../../hooks/useDashboardItems';
|
|
@@ -39,10 +39,6 @@ export var useGraphTooltipMetaInfo = function useGraphTooltipMetaInfo(_ref) {
|
|
|
39
39
|
var functionSystemName = (_arrowToString2 = arrowToString((_table$getChild7 = table.getChild(FIELD_FUNCTION_SYSTEM_NAME)) === null || _table$getChild7 === void 0 ? void 0 : _table$getChild7.get(row))) !== null && _arrowToString2 !== void 0 ? _arrowToString2 : '';
|
|
40
40
|
var functionStartLine = (_table$getChild$get3 = (_table$getChild8 = table.getChild(FIELD_FUNCTION_START_LINE)) === null || _table$getChild8 === void 0 ? void 0 : _table$getChild8.get(row)) !== null && _table$getChild$get3 !== void 0 ? _table$getChild$get3 : 0n;
|
|
41
41
|
var lineNumber = locationLine !== 0n ? locationLine : functionStartLine !== 0n ? functionStartLine : undefined;
|
|
42
|
-
var labelPrefix = 'labels.';
|
|
43
|
-
var labelColumnNames = table.schema.fields.filter(function (field) {
|
|
44
|
-
return field.name.startsWith(labelPrefix);
|
|
45
|
-
});
|
|
46
42
|
var timestamp = (_table$getChild9 = table.getChild(FIELD_TIMESTAMP)) === null || _table$getChild9 === void 0 ? void 0 : _table$getChild9.get(row);
|
|
47
43
|
var _useParcaContext = useParcaContext(),
|
|
48
44
|
queryServiceClient = _useParcaContext.queryServiceClient,
|
|
@@ -67,12 +63,7 @@ export var useGraphTooltipMetaInfo = function useGraphTooltipMetaInfo(_ref) {
|
|
|
67
63
|
return "".concat(functionFilename, " ").concat(lineNumber !== undefined ? " +".concat(lineNumber.toString()) : '');
|
|
68
64
|
};
|
|
69
65
|
var file = getTextForFile();
|
|
70
|
-
var labelPairs =
|
|
71
|
-
var _arrowToString3, _table$getChild0;
|
|
72
|
-
return [labelColumnNames[i].name.slice(labelPrefix.length), (_arrowToString3 = arrowToString((_table$getChild0 = table.getChild(field_0.name)) === null || _table$getChild0 === void 0 ? void 0 : _table$getChild0.get(row))) !== null && _arrowToString3 !== void 0 ? _arrowToString3 : ''];
|
|
73
|
-
}).filter(function (value) {
|
|
74
|
-
return value[1] !== '';
|
|
75
|
-
});
|
|
66
|
+
var labelPairs = getLabelPairs(table, row);
|
|
76
67
|
var _useDashboardItems = useDashboardItems(),
|
|
77
68
|
dashboardItems = _useDashboardItems.dashboardItems,
|
|
78
69
|
setDashboardItems = _useDashboardItems.setDashboardItems;
|
|
@@ -19,6 +19,7 @@ export interface CurrentPathFrame {
|
|
|
19
19
|
labels?: string;
|
|
20
20
|
}
|
|
21
21
|
export declare const getCurrentPathFrameData: (table: Table, row: number) => CurrentPathFrame;
|
|
22
|
+
export declare function getLabelPairs(table: Table, row: number): Array<[string, string]>;
|
|
22
23
|
export declare function isCurrentPathFrameMatch(table: Table, row: number, b: CurrentPathFrame): boolean;
|
|
23
24
|
export declare function getMaxDepth(depthColumn: Column<number> | null): number;
|
|
24
25
|
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/ProfileFlameGraph/FlameGraphArrow/utils.ts"],"names":[],"mappings":"AAaA,OAAO,EAAC,MAAM,EAAE,KAAK,EAAC,MAAM,mBAAmB,CAAC;AAEhD,OAAO,EAIL,KAAK,aAAa,EAClB,KAAK,eAAe,EACrB,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAC,aAAa,EAAwB,MAAM,qBAAqB,CAAC;AACzE,OAAO,EAAC,SAAS,EAAgB,MAAM,aAAa,CAAC;AAWrD,wBAAgB,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,cAAc,EAAE,OAAO,GAAG,MAAM,CAuBpF;AAED,eAAO,MAAM,cAAc,GAAI,SAAS,MAAM,KAAG,aAMhD,CAAC;AAEF,eAAO,MAAM,sBAAsB,GAAI,UAAU,MAAM,KAAG,eAMzD,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAC/B,wBAAwB,MAAM,EAC9B,iBAAiB,MAAM,EACvB,OAAO,MAAM,EACb,MAAM,MAAM,KACX,MAOF,CAAC;AAEF,eAAO,MAAM,6BAA6B,GACxC,wBAAwB,MAAM,EAC9B,MAAM,MAAM,KACX,MAMF,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,QAAQ,GAAG,KAAG,MAAM,GAAG,IAQpD,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAAI,gBAAgB,aAAa,KAAG,SAyBvE,CAAC;AAEF,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,uBAAuB,GAAI,OAAO,KAAK,EAAE,KAAK,MAAM,KAAG,gBAwBnE,CAAC;
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/ProfileFlameGraph/FlameGraphArrow/utils.ts"],"names":[],"mappings":"AAaA,OAAO,EAAC,MAAM,EAAE,KAAK,EAAC,MAAM,mBAAmB,CAAC;AAEhD,OAAO,EAIL,KAAK,aAAa,EAClB,KAAK,eAAe,EACrB,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAC,aAAa,EAAwB,MAAM,qBAAqB,CAAC;AACzE,OAAO,EAAC,SAAS,EAAgB,MAAM,aAAa,CAAC;AAWrD,wBAAgB,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,cAAc,EAAE,OAAO,GAAG,MAAM,CAuBpF;AAED,eAAO,MAAM,cAAc,GAAI,SAAS,MAAM,KAAG,aAMhD,CAAC;AAEF,eAAO,MAAM,sBAAsB,GAAI,UAAU,MAAM,KAAG,eAMzD,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAC/B,wBAAwB,MAAM,EAC9B,iBAAiB,MAAM,EACvB,OAAO,MAAM,EACb,MAAM,MAAM,KACX,MAOF,CAAC;AAEF,eAAO,MAAM,6BAA6B,GACxC,wBAAwB,MAAM,EAC9B,MAAM,MAAM,KACX,MAMF,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,QAAQ,GAAG,KAAG,MAAM,GAAG,IAQpD,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAAI,gBAAgB,aAAa,KAAG,SAyBvE,CAAC;AAEF,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,uBAAuB,GAAI,OAAO,KAAK,EAAE,KAAK,MAAM,KAAG,gBAwBnE,CAAC;AAEF,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,GAAG,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAUhF;AAQD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAW/F;AAED,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,IAAI,GAAG,MAAM,CAStE"}
|
|
@@ -126,7 +126,7 @@ export var getCurrentPathFrameData = function getCurrentPathFrameData(table, row
|
|
|
126
126
|
labels: labels !== null && labels !== void 0 ? labels : undefined
|
|
127
127
|
};
|
|
128
128
|
};
|
|
129
|
-
function
|
|
129
|
+
export function getLabelPairs(table, row) {
|
|
130
130
|
var labelPrefix = 'labels.';
|
|
131
131
|
var labelColumnNames = table.schema.fields.filter(function (field) {
|
|
132
132
|
return field.name.startsWith(labelPrefix);
|
|
@@ -136,7 +136,10 @@ function getLabelSet(table, row) {
|
|
|
136
136
|
return [labelColumnNames[i].name.slice(labelPrefix.length), (_arrowToString = arrowToString((_table$getChild12 = table.getChild(field.name)) === null || _table$getChild12 === void 0 ? void 0 : _table$getChild12.get(row))) !== null && _arrowToString !== void 0 ? _arrowToString : ''];
|
|
137
137
|
}).filter(function (value) {
|
|
138
138
|
return value[1] !== '';
|
|
139
|
-
})
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
function getLabelSet(table, row) {
|
|
142
|
+
return getLabelPairs(table, row).map(function (_ref) {
|
|
140
143
|
var _ref2 = _slicedToArray(_ref, 2),
|
|
141
144
|
k = _ref2[0],
|
|
142
145
|
v = _ref2[1];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileTypeSelector/index.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAC,QAAQ,EAAC,MAAM,0BAA0B,CAAC;AAElD,OAAO,EAAC,WAAW,EAAE,oBAAoB,EAAC,MAAM,eAAe,CAAC;AAChE,OAAO,EAAS,KAAK,aAAa,EAAC,MAAM,mBAAmB,CAAC;AAG7D,UAAU,gBAAgB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,iBAAiB;IACzB,CAAC,GAAG,EAAE,MAAM,GAAG,gBAAgB,CAAC;CACjC;AAED,eAAO,MAAM,iBAAiB,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileTypeSelector/index.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAC,QAAQ,EAAC,MAAM,0BAA0B,CAAC;AAElD,OAAO,EAAC,WAAW,EAAE,oBAAoB,EAAC,MAAM,eAAe,CAAC;AAChE,OAAO,EAAS,KAAK,aAAa,EAAC,MAAM,mBAAmB,CAAC;AAG7D,UAAU,gBAAgB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,iBAAiB;IACzB,CAAC,GAAG,EAAE,MAAM,GAAG,gBAAgB,CAAC;CACjC;AAED,eAAO,MAAM,iBAAiB,EAAE,iBAmG/B,CAAC;AAEF,wBAAgB,gCAAgC,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAU3F;AAED,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,8BAA8B,EAAE,OAAO,GACtC,aAAa,CAiBf;AAED,eAAO,MAAM,oBAAoB,GAAI,MAAM,WAAW,KAAG,MAIxD,CAAC;AAEF,eAAO,MAAM,yBAAyB,GAAI,OAAO,WAAW,EAAE,KAAG,MAAM,EAItE,CAAC;AAEF,UAAU,KAAK;IACb,gBAAgB,CAAC,EAAE,oBAAoB,CAAC;IACxC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC5B,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,8BAA8B,CAAC,EAAE,OAAO,CAAC;IACzC,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IACjD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,QAAA,MAAM,mBAAmB,GAAI,2GAQ1B,KAAK,KAAG,GAAG,CAAC,OA2Bd,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
|
|
@@ -100,21 +100,23 @@ export var wellKnownProfiles = {
|
|
|
100
100
|
name: 'Off-CPU',
|
|
101
101
|
help: 'Time spent off the CPU as observed by the Parca Agent.'
|
|
102
102
|
},
|
|
103
|
+
// deprecated with PC sampling
|
|
103
104
|
'parca_agent:cuda:nanoseconds:cuda:nanoseconds:delta': {
|
|
104
105
|
name: 'On-GPU',
|
|
105
106
|
help: 'Time spent on the GPU.'
|
|
106
107
|
},
|
|
108
|
+
// use this for combined PC stall and kernel timing, not the default
|
|
107
109
|
'parca_agent:gpu_time:nanoseconds:gpu_time:nanoseconds:delta': {
|
|
108
110
|
name: 'On-GPU',
|
|
109
111
|
help: 'Time spent on the GPU. Combines kernel execution time and PC stall samples; the gpu_view label distinguishes the two views.'
|
|
110
112
|
},
|
|
111
113
|
'parca_agent:gpu_kernel_time:nanoseconds:gpu_kernel_time:nanoseconds:delta': {
|
|
112
|
-
name: '
|
|
114
|
+
name: 'GPU Kernels',
|
|
113
115
|
help: 'GPU kernel execution time measured via CUDA runtime callbacks.'
|
|
114
116
|
},
|
|
115
|
-
'parca_agent:
|
|
116
|
-
name: 'GPU
|
|
117
|
-
help: '
|
|
117
|
+
'parca_agent:gpu_pcsample:count:gpu_pcsample:nanoseconds:delta': {
|
|
118
|
+
name: 'GPU Instructions',
|
|
119
|
+
help: 'PC samples from the GPU — all PC activity, not just stalls; shows the instruction/stall reason.'
|
|
118
120
|
}
|
|
119
121
|
};
|
|
120
122
|
export function flexibleWellKnownProfileMatching(name) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parca/profile",
|
|
3
|
-
"version": "0.19.
|
|
3
|
+
"version": "0.19.155",
|
|
4
4
|
"description": "Profile viewing libraries",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"@floating-ui/react": "^0.27.12",
|
|
@@ -89,5 +89,5 @@
|
|
|
89
89
|
"access": "public",
|
|
90
90
|
"registry": "https://registry.npmjs.org/"
|
|
91
91
|
},
|
|
92
|
-
"gitHead": "
|
|
92
|
+
"gitHead": "c16730288b7d5f5684ebebfd8f505c7d0fcb99b8"
|
|
93
93
|
}
|
|
@@ -20,9 +20,10 @@ import {useParcaContext} from '@parca/components';
|
|
|
20
20
|
import {ProfileType} from '@parca/parser';
|
|
21
21
|
import {formatDateTimeDownToMS, getLastItem} from '@parca/utilities';
|
|
22
22
|
|
|
23
|
+
import {getLabelPairs} from '../ProfileFlameGraph/FlameGraphArrow/utils';
|
|
23
24
|
import {hexifyAddress, truncateString, truncateStringReverse} from '../utils';
|
|
24
25
|
import {ExpandOnHover} from './ExpandOnHoverValue';
|
|
25
|
-
import {
|
|
26
|
+
import {gpuFrameInfosFromLabels, type GpuFrameInfo} from './gpuFrameDescriptions';
|
|
26
27
|
import {openInNewTab} from './openInNewTab';
|
|
27
28
|
import {useGraphTooltip} from './useGraphTooltip';
|
|
28
29
|
import {useGraphTooltipMetaInfo} from './useGraphTooltipMetaInfo';
|
|
@@ -78,7 +79,7 @@ const GraphTooltipArrowContent = ({
|
|
|
78
79
|
row: rowNumber,
|
|
79
80
|
} = graphTooltipData;
|
|
80
81
|
|
|
81
|
-
const
|
|
82
|
+
const gpuInfos = gpuFrameInfosFromLabels(getLabelPairs(table, rowNumber));
|
|
82
83
|
|
|
83
84
|
// Outer card gains a subtle ring when frozen, matching the design's
|
|
84
85
|
// `.is-frozen` treatment.
|
|
@@ -135,7 +136,15 @@ const GraphTooltipArrowContent = ({
|
|
|
135
136
|
</table>
|
|
136
137
|
</div>
|
|
137
138
|
</div>
|
|
138
|
-
{info
|
|
139
|
+
{gpuInfos.map((info, i) => (
|
|
140
|
+
<GpuDescriptionBlock
|
|
141
|
+
key={i}
|
|
142
|
+
info={info}
|
|
143
|
+
// When both a SASS and a stall block are shown, keep the tooltip
|
|
144
|
+
// compact by trimming the (typically longer) stall description.
|
|
145
|
+
maxSentences={gpuInfos.length > 1 && info.kind === 'stall' ? 2 : undefined}
|
|
146
|
+
/>
|
|
147
|
+
))}
|
|
139
148
|
<ShortcutFooter frozen={frozen} />
|
|
140
149
|
</div>
|
|
141
150
|
</div>
|
|
@@ -143,8 +152,26 @@ const GraphTooltipArrowContent = ({
|
|
|
143
152
|
);
|
|
144
153
|
};
|
|
145
154
|
|
|
146
|
-
|
|
155
|
+
// Trims a description to at most `max` sentences, appending an ellipsis when
|
|
156
|
+
// anything was dropped.
|
|
157
|
+
const truncateToSentences = (text: string, max: number): string => {
|
|
158
|
+
const sentences = text.match(/[^.!?]+[.!?]+(\s|$)|[^.!?]+$/g);
|
|
159
|
+
if (sentences === null || sentences.length <= max) return text;
|
|
160
|
+
return `${sentences.slice(0, max).join('').trimEnd()} …`;
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
const GpuDescriptionBlock = ({
|
|
164
|
+
info,
|
|
165
|
+
maxSentences,
|
|
166
|
+
}: {
|
|
167
|
+
info: GpuFrameInfo;
|
|
168
|
+
maxSentences?: number;
|
|
169
|
+
}): React.JSX.Element => {
|
|
147
170
|
const chipPrefix = info.kind === 'stall' ? 'Stall reason' : 'SASS instruction';
|
|
171
|
+
const description =
|
|
172
|
+
maxSentences === undefined
|
|
173
|
+
? info.entry.description
|
|
174
|
+
: truncateToSentences(info.entry.description, maxSentences);
|
|
148
175
|
|
|
149
176
|
return (
|
|
150
177
|
<div className="mx-2 mt-3 border-t border-gray-200 pt-3 dark:border-gray-700">
|
|
@@ -154,9 +181,7 @@ const GpuDescriptionBlock = ({info}: {info: GpuFrameInfo}): React.JSX.Element =>
|
|
|
154
181
|
<div className="font-mono text-[10px] uppercase tracking-wider text-gray-500 dark:text-gray-400">
|
|
155
182
|
Description
|
|
156
183
|
</div>
|
|
157
|
-
<p className="mt-1 text-xs leading-relaxed text-gray-600 dark:text-gray-300">
|
|
158
|
-
{info.entry.description}
|
|
159
|
-
</p>
|
|
184
|
+
<p className="mt-1 text-xs leading-relaxed text-gray-600 dark:text-gray-300">{description}</p>
|
|
160
185
|
<button
|
|
161
186
|
type="button"
|
|
162
187
|
onClick={e => {
|
|
@@ -13,7 +13,14 @@
|
|
|
13
13
|
|
|
14
14
|
import {describe, expect, test} from 'vitest';
|
|
15
15
|
|
|
16
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
CUDA_SASS_INSTRUCTION_LABEL,
|
|
18
|
+
CUDA_STALL_REASON_LABEL,
|
|
19
|
+
SASS_SOURCE_URL,
|
|
20
|
+
STALL_SOURCE_URL,
|
|
21
|
+
gpuFrameInfo,
|
|
22
|
+
gpuFrameInfosFromLabels,
|
|
23
|
+
} from './gpuFrameDescriptions';
|
|
17
24
|
|
|
18
25
|
describe('gpuFrameInfo', () => {
|
|
19
26
|
test.each([
|
|
@@ -51,3 +58,37 @@ describe('gpuFrameInfo', () => {
|
|
|
51
58
|
}
|
|
52
59
|
);
|
|
53
60
|
});
|
|
61
|
+
|
|
62
|
+
describe('gpuFrameInfosFromLabels', () => {
|
|
63
|
+
test('returns a single SASS info for the cuda_sass_instruction label', () => {
|
|
64
|
+
const infos = gpuFrameInfosFromLabels([[CUDA_SASS_INSTRUCTION_LABEL, 'STS']]);
|
|
65
|
+
expect(infos).toHaveLength(1);
|
|
66
|
+
expect(infos[0].kind).toBe('sass');
|
|
67
|
+
expect(infos[0].entry.description).toBe('Store to Shared Memory');
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
test('returns a single stall info for the cuda_stall_reason label', () => {
|
|
71
|
+
const infos = gpuFrameInfosFromLabels([
|
|
72
|
+
[CUDA_STALL_REASON_LABEL, 'smsp__pcsamp_warps_issue_stalled_long_scoreboard'],
|
|
73
|
+
]);
|
|
74
|
+
expect(infos).toHaveLength(1);
|
|
75
|
+
expect(infos[0].kind).toBe('stall');
|
|
76
|
+
expect(infos[0].entry.reasonLabel).toBe('Long Scoreboard');
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test('returns SASS first then stall when both labels are present', () => {
|
|
80
|
+
const infos = gpuFrameInfosFromLabels([
|
|
81
|
+
[CUDA_STALL_REASON_LABEL, 'smsp__pcsamp_warps_issue_stalled_long_scoreboard'],
|
|
82
|
+
[CUDA_SASS_INSTRUCTION_LABEL, 'STS'],
|
|
83
|
+
]);
|
|
84
|
+
expect(infos.map(i => i.kind)).toEqual(['sass', 'stall']);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
test('ignores non-cuda labels and unknown values', () => {
|
|
88
|
+
expect(gpuFrameInfosFromLabels([['service', 'api']])).toEqual([]);
|
|
89
|
+
expect(gpuFrameInfosFromLabels([[CUDA_SASS_INSTRUCTION_LABEL, 'NOT_A_REAL_OPCODE']])).toEqual(
|
|
90
|
+
[]
|
|
91
|
+
);
|
|
92
|
+
expect(gpuFrameInfosFromLabels([])).toEqual([]);
|
|
93
|
+
});
|
|
94
|
+
});
|
|
@@ -530,27 +530,56 @@ function stallSourceUrl(name: string): string {
|
|
|
530
530
|
return `${STALL_SOURCE_URL}:~:text=${encodeURIComponent(name)}`;
|
|
531
531
|
}
|
|
532
532
|
|
|
533
|
+
// Node label keys under which GPU PC-sampling values now arrive. The SASS
|
|
534
|
+
// mnemonic and warp stall reason used to be the leaf frame's function name;
|
|
535
|
+
// they are now carried as node labels.
|
|
536
|
+
export const CUDA_SASS_INSTRUCTION_LABEL = 'cuda_sass_instruction';
|
|
537
|
+
export const CUDA_STALL_REASON_LABEL = 'cuda_stall_reason';
|
|
538
|
+
|
|
539
|
+
function sassInfo(name: string): GpuFrameInfo | undefined {
|
|
540
|
+
if (name === '') return undefined;
|
|
541
|
+
const sass = SASS_INSTRUCTION_DESCRIPTIONS[name];
|
|
542
|
+
if (sass === undefined) return undefined;
|
|
543
|
+
return {
|
|
544
|
+
kind: 'sass',
|
|
545
|
+
entry: sass,
|
|
546
|
+
sourceLabel: NVIDIA_DOCS_LABEL,
|
|
547
|
+
sourceUrl: sass.sourceUrl ?? SASS_SOURCE_URL,
|
|
548
|
+
};
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
function stallInfo(name: string): GpuFrameInfo | undefined {
|
|
552
|
+
if (name === '') return undefined;
|
|
553
|
+
const stall = STALL_REASON_DESCRIPTIONS[name];
|
|
554
|
+
if (stall === undefined) return undefined;
|
|
555
|
+
return {
|
|
556
|
+
kind: 'stall',
|
|
557
|
+
entry: stall,
|
|
558
|
+
sourceLabel: NVIDIA_DOCS_LABEL,
|
|
559
|
+
sourceUrl: stall.sourceUrl ?? stallSourceUrl(name),
|
|
560
|
+
};
|
|
561
|
+
}
|
|
562
|
+
|
|
533
563
|
// Resolves a frame name to its GPU info, or undefined if not a known SASS
|
|
534
564
|
// mnemonic or PC-sampling reason. Both tables are exact-match lookups.
|
|
535
565
|
export function gpuFrameInfo(name: string): GpuFrameInfo | undefined {
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
566
|
+
return sassInfo(name) ?? stallInfo(name);
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
// Resolves GPU info from a node's labels. A node may carry both a SASS
|
|
570
|
+
// instruction and a stall reason label, so this returns an array (SASS first,
|
|
571
|
+
// then stall) of the entries that matched a known description.
|
|
572
|
+
export function gpuFrameInfosFromLabels(labelPairs: Array<[string, string]>): GpuFrameInfo[] {
|
|
573
|
+
const infos: GpuFrameInfo[] = [];
|
|
574
|
+
const sassValue = labelPairs.find(([key]) => key === CUDA_SASS_INSTRUCTION_LABEL)?.[1];
|
|
575
|
+
const stallValue = labelPairs.find(([key]) => key === CUDA_STALL_REASON_LABEL)?.[1];
|
|
576
|
+
if (sassValue !== undefined) {
|
|
577
|
+
const info = sassInfo(sassValue);
|
|
578
|
+
if (info !== undefined) infos.push(info);
|
|
545
579
|
}
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
kind: 'stall',
|
|
550
|
-
entry: stall,
|
|
551
|
-
sourceLabel: NVIDIA_DOCS_LABEL,
|
|
552
|
-
sourceUrl: stall.sourceUrl ?? stallSourceUrl(name),
|
|
553
|
-
};
|
|
580
|
+
if (stallValue !== undefined) {
|
|
581
|
+
const info = stallInfo(stallValue);
|
|
582
|
+
if (info !== undefined) infos.push(info);
|
|
554
583
|
}
|
|
555
|
-
return
|
|
584
|
+
return infos;
|
|
556
585
|
}
|
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
FIELD_MAPPING_FILE,
|
|
29
29
|
FIELD_TIMESTAMP,
|
|
30
30
|
} from '../../ProfileFlameGraph/FlameGraphArrow';
|
|
31
|
-
import {arrowToString} from '../../ProfileFlameGraph/FlameGraphArrow/utils';
|
|
31
|
+
import {arrowToString, getLabelPairs} from '../../ProfileFlameGraph/FlameGraphArrow/utils';
|
|
32
32
|
import {ProfileSource} from '../../ProfileSource';
|
|
33
33
|
import {useProfileViewContext} from '../../ProfileView/context/ProfileViewContext';
|
|
34
34
|
import {stringParam} from '../../hooks/urlParsers';
|
|
@@ -69,8 +69,6 @@ export const useGraphTooltipMetaInfo = ({table, row}: Props): GraphTooltipMetaIn
|
|
|
69
69
|
const functionStartLine: bigint = table.getChild(FIELD_FUNCTION_START_LINE)?.get(row) ?? 0n;
|
|
70
70
|
const lineNumber =
|
|
71
71
|
locationLine !== 0n ? locationLine : functionStartLine !== 0n ? functionStartLine : undefined;
|
|
72
|
-
const labelPrefix = 'labels.';
|
|
73
|
-
const labelColumnNames = table.schema.fields.filter(field => field.name.startsWith(labelPrefix));
|
|
74
72
|
const timestamp = table.getChild(FIELD_TIMESTAMP)?.get(row);
|
|
75
73
|
|
|
76
74
|
const {queryServiceClient, enableSourcesView} = useParcaContext();
|
|
@@ -103,12 +101,7 @@ export const useGraphTooltipMetaInfo = ({table, row}: Props): GraphTooltipMetaIn
|
|
|
103
101
|
};
|
|
104
102
|
const file = getTextForFile();
|
|
105
103
|
|
|
106
|
-
const labelPairs: Array<[string, string]> =
|
|
107
|
-
.map((field, i) => [
|
|
108
|
-
labelColumnNames[i].name.slice(labelPrefix.length),
|
|
109
|
-
arrowToString(table.getChild(field.name)?.get(row)) ?? '',
|
|
110
|
-
])
|
|
111
|
-
.filter(value => value[1] !== '') as Array<[string, string]>;
|
|
104
|
+
const labelPairs: Array<[string, string]> = getLabelPairs(table, row);
|
|
112
105
|
|
|
113
106
|
const {dashboardItems, setDashboardItems} = useDashboardItems();
|
|
114
107
|
|
|
@@ -173,7 +173,7 @@ export const getCurrentPathFrameData = (table: Table, row: number): CurrentPathF
|
|
|
173
173
|
};
|
|
174
174
|
};
|
|
175
175
|
|
|
176
|
-
function
|
|
176
|
+
export function getLabelPairs(table: Table, row: number): Array<[string, string]> {
|
|
177
177
|
const labelPrefix = 'labels.';
|
|
178
178
|
const labelColumnNames = table.schema.fields.filter(field => field.name.startsWith(labelPrefix));
|
|
179
179
|
|
|
@@ -182,7 +182,11 @@ function getLabelSet(table: Table, row: number): string {
|
|
|
182
182
|
labelColumnNames[i].name.slice(labelPrefix.length),
|
|
183
183
|
arrowToString(table.getChild(field.name)?.get(row)) ?? '',
|
|
184
184
|
])
|
|
185
|
-
.filter(value => value[1] !== '')
|
|
185
|
+
.filter(value => value[1] !== '') as Array<[string, string]>;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function getLabelSet(table: Table, row: number): string {
|
|
189
|
+
return getLabelPairs(table, row)
|
|
186
190
|
.map(([k, v]) => `${k}="${v}"`)
|
|
187
191
|
.join(', ');
|
|
188
192
|
}
|
|
@@ -107,21 +107,23 @@ export const wellKnownProfiles: WellKnownProfiles = {
|
|
|
107
107
|
name: 'Off-CPU',
|
|
108
108
|
help: 'Time spent off the CPU as observed by the Parca Agent.',
|
|
109
109
|
},
|
|
110
|
+
// deprecated with PC sampling
|
|
110
111
|
'parca_agent:cuda:nanoseconds:cuda:nanoseconds:delta': {
|
|
111
112
|
name: 'On-GPU',
|
|
112
113
|
help: 'Time spent on the GPU.',
|
|
113
114
|
},
|
|
115
|
+
// use this for combined PC stall and kernel timing, not the default
|
|
114
116
|
'parca_agent:gpu_time:nanoseconds:gpu_time:nanoseconds:delta': {
|
|
115
117
|
name: 'On-GPU',
|
|
116
118
|
help: 'Time spent on the GPU. Combines kernel execution time and PC stall samples; the gpu_view label distinguishes the two views.',
|
|
117
119
|
},
|
|
118
120
|
'parca_agent:gpu_kernel_time:nanoseconds:gpu_kernel_time:nanoseconds:delta': {
|
|
119
|
-
name: '
|
|
121
|
+
name: 'GPU Kernels',
|
|
120
122
|
help: 'GPU kernel execution time measured via CUDA runtime callbacks.',
|
|
121
123
|
},
|
|
122
|
-
'parca_agent:
|
|
123
|
-
name: 'GPU
|
|
124
|
-
help: '
|
|
124
|
+
'parca_agent:gpu_pcsample:count:gpu_pcsample:nanoseconds:delta': {
|
|
125
|
+
name: 'GPU Instructions',
|
|
126
|
+
help: 'PC samples from the GPU — all PC activity, not just stalls; shows the instruction/stall reason.',
|
|
125
127
|
},
|
|
126
128
|
};
|
|
127
129
|
|