GH-140643: Add <native> and <GC> frames to the sampling profiler (#141108)

- Introduce a new field in the GC state to store the frame that initiated garbage collection.
- Update RemoteUnwinder to include options for including "<native>" and "<GC>" frames in the stack trace.
- Modify the sampling profiler to accept parameters for controlling the inclusion of native and GC frames.
- Enhance the stack collector to properly format and append these frames during profiling.
- Add tests to verify the correct behavior of the profiler with respect to native and GC frames, including options to exclude them.

Co-authored-by: Pablo Galindo Salgado <pablogsal@gmail.com>
This commit is contained in:
Brandt Bucher 2025-11-17 05:39:00 -08:00 committed by GitHub
parent 89a914c58d
commit 336366fd7c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 465 additions and 86 deletions

View file

@ -151,17 +151,22 @@ function createPythonTooltip(data) {
const funcname = resolveString(d.data.funcname) || resolveString(d.data.name);
const filename = resolveString(d.data.filename) || "";
// Don't show file location for special frames like <GC> and <native>
const isSpecialFrame = filename === "~";
const fileLocationHTML = isSpecialFrame ? "" : `
<div style="color: #5a6c7d; font-size: 13px; margin-bottom: 12px;
font-family: monospace; background: #f8f9fa;
padding: 4px 8px; border-radius: 4px; word-break: break-all; overflow-wrap: break-word;">
${filename}${d.data.lineno ? ":" + d.data.lineno : ""}
</div>`;
const tooltipHTML = `
<div>
<div style="color: #3776ab; font-weight: 600; font-size: 16px;
margin-bottom: 8px; line-height: 1.3; word-break: break-word; overflow-wrap: break-word;">
${funcname}
</div>
<div style="color: #5a6c7d; font-size: 13px; margin-bottom: 12px;
font-family: monospace; background: #f8f9fa;
padding: 4px 8px; border-radius: 4px; word-break: break-all; overflow-wrap: break-word;">
${filename}${d.data.lineno ? ":" + d.data.lineno : ""}
</div>
${fileLocationHTML}
<div style="display: grid; grid-template-columns: auto 1fr;
gap: 8px 16px; font-size: 14px;">
<span style="color: #5a6c7d; font-weight: 500;">Execution Time:</span>
@ -474,14 +479,23 @@ function populateStats(data) {
if (i < hotSpots.length && hotSpots[i]) {
const hotspot = hotSpots[i];
const filename = hotspot.filename || 'unknown';
const basename = filename !== 'unknown' ? filename.split('/').pop() : 'unknown';
const lineno = hotspot.lineno ?? '?';
let funcDisplay = hotspot.funcname || 'unknown';
if (funcDisplay.length > 35) {
funcDisplay = funcDisplay.substring(0, 32) + '...';
}
document.getElementById(`hotspot-file-${num}`).textContent = `${basename}:${lineno}`;
// Don't show file:line for special frames like <GC> and <native>
const isSpecialFrame = filename === '~' && (lineno === 0 || lineno === '?');
let fileDisplay;
if (isSpecialFrame) {
fileDisplay = '--';
} else {
const basename = filename !== 'unknown' ? filename.split('/').pop() : 'unknown';
fileDisplay = `${basename}:${lineno}`;
}
document.getElementById(`hotspot-file-${num}`).textContent = fileDisplay;
document.getElementById(`hotspot-func-${num}`).textContent = funcDisplay;
document.getElementById(`hotspot-detail-${num}`).textContent = `${hotspot.directPercent.toFixed(1)}% samples (${hotspot.directSamples.toLocaleString()})`;
} else {