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

@ -36,10 +36,16 @@ def process_frames(self, frames, thread_id):
def export(self, filename):
lines = []
for (call_tree, thread_id), count in self.stack_counter.items():
stack_str = ";".join(
f"{os.path.basename(f[0])}:{f[2]}:{f[1]}" for f in call_tree
)
lines.append((f"tid:{thread_id};{stack_str}", count))
parts = [f"tid:{thread_id}"]
for file, line, func in call_tree:
# This is what pstats does for "special" frames:
if file == "~" and line == 0:
part = func
else:
part = f"{os.path.basename(file)}:{func}:{line}"
parts.append(part)
stack_str = ";".join(parts)
lines.append((stack_str, count))
lines.sort(key=lambda x: (-x[1], x[0]))
@ -98,6 +104,10 @@ def export(self, filename):
def _format_function_name(func):
filename, lineno, funcname = func
# Special frames like <GC> and <native> should not show file:line
if filename == "~" and lineno == 0:
return funcname
if len(filename) > 50:
parts = filename.split("/")
if len(parts) > 2: