Skip to content

Make async-profiler per-thread profiling opt-in for Java - #82

Merged
artursarlo merged 1 commit into
masterfrom
java-async-profiler-per-thread-opt-in
Sep 22, 2026
Merged

artursarlo merged 1 commit into
masterfrom
java-async-profiler-per-thread-opt-in

Conversation

@artursarlo

Copy link
Copy Markdown

Make async-profiler per-thread profiling opt-in for Java

Summary

Per-thread profiling — async-profiler's threads output option, which splits collapsed stacks by thread name — was hard-coded on in PR #78 via FORMAT_PARAMS = "ann,sig,threads". That output is needed for Spark task attribution but adds cardinality/overhead that isn't desirable for every workload.

This PR makes per-thread profiling opt-in and disabled by default, controllable both from the CLI and from the heartbeat / command-control system. This is the agent-side change; the backend counterpart (surfacing the per_thread toggle in the profiling command) will be implemented against this PR.

Changes

  • gprofiler/profilers/java.py
    • Reverted FORMAT_PARAMS back to "ann,sig".
    • Added per_thread: bool = False to AsyncProfiledProcess; when set it appends ,threads to the async-profiler output args (same pattern as includemm / includeln).
    • New CLI flag --java-async-profiler-per-thread (store_true, default False), threaded through JavaProfiler.
  • gprofiler/dynamic_profiling_management/__init__.py
    • _apply_profiler_configs now reads an optional per_thread key from the async_profiler command config (default False) and sets java_async_profiler_per_thread.
  • docs/HEARTBEAT_SYSTEM_README.md — documented the new per_thread field and added an example.
  • tests/utils.py — threaded java_async_profiler_per_thread through make_java_profiler.

How to enable

  • CLI: pass --java-async-profiler-per-thread.
  • Heartbeat/command config:
    { "async_profiler": { "enabled": true, "time": "cpu", "per_thread": true } }

Behavior change

Default flamegraphs no longer include per-thread splitting. Deployments relying on per-thread output (e.g. Spark task attribution) must opt in via the flag or command config.

Backend follow-up

The backend needs to accept and forward the per_thread boolean in the async_profiler profiler config so it reaches the agent through the heartbeat response (default false for backward compatibility).

Test plan

  • Unit: assert AP output args include/exclude ,threads based on the flag.
  • Verify heartbeat command with per_thread: true/false produces expected flamegraphs.

Per-thread profiling (async-profiler's 'threads' output option) was hard-coded on
via FORMAT_PARAMS. Make it opt-in and disabled by default, controllable both via
CLI and the heartbeat/command-control system.

- java.py: drop 'threads' from FORMAT_PARAMS; add per_thread flag to
  AsyncProfiledProcess and a --java-async-profiler-per-thread CLI arg (store_true,
  default False) wired through JavaProfiler.
- dynamic_profiling_management: map async_profiler config 'per_thread' key
  (default False) to java_async_profiler_per_thread.
- docs/HEARTBEAT_SYSTEM_README.md: document the per_thread field.
- tests/utils.py: thread the new arg through make_java_profiler.
@artursarlo
artursarlo merged commit 616921b into master Sep 22, 2026
17 of 22 checks passed
artursarlo added a commit to pinterest/gprofiler-performance-studio that referenced this pull request Sep 22, 2026
Adds an opt-in, disabled-by-default 'Per-Thread' checkbox to the Async Profiler card in the profiling request interface. When enabled it sets async_profiler.per_thread=true in profiler_configs, which the agent maps to async-profiler's 'threads' output (per pinterest/gprofiler#82). Flows through additional_args unchanged; no backend change required.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant