#1678: Eliminate redundant listing of profiler arguments

This commit is contained in:
Andrei Pangin
2026-02-06 23:20:30 +00:00
parent 31042f13bc
commit 68244fbf6f
5 changed files with 37 additions and 108 deletions

View File

@@ -12,9 +12,14 @@ $ java -agentpath:/path/to/libasyncProfiler.so=start,event=cpu,file=profile.html
On macOS, the library name is `libasyncProfiler.dylib` instead of `libasyncProfiler.so`.
Agent library is configured through the JVMTI argument interface.
The format of the arguments string is described
[in the source code](https://github.com/async-profiler/async-profiler/blob/v4.3/src/arguments.cpp#L39).
`asprof` actually converts command line arguments to that format.
The argument string is a comma-separated list of [profiler options](ProfilerOptions.md):
```
option[=value],option[=value]...
```
`asprof` internally converts command line arguments to the above format and attaches
`libasyncProfiler.so` agent to a running process.
Another important use of attaching async-profiler as an agent is for continuous profiling.

View File

@@ -22,13 +22,15 @@ The below options are `action`s for async-profiler and common for both `asprof`
| `metrics` | Print profiler metrics in Prometheus format. |
| `list` | Show the list of profiling events available for the target process specified with PID. |
## Options applicable to any output format
## General options
| asprof | Launch as agent | Description |
| -------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `-o fmt` | `fmt` | Specifies what information to dump when profiling ends. For various dump option details, please refer to [Dump Option Appendix](#dump-option). |
| `-f FILENAME` | `file=FILENAME` | The file name to dump the profile information to.<br>`%p` in the file name is expanded to the PID of the target JVM;<br>`%t` - to the timestamp;<br>`%n{MAX}` - to the sequence number;<br>`%{ENV}` - to the value of the given environment variable.<br>Example: `asprof -o collapsed -f /tmp/traces-%t.txt 8983` |
| `-d N` | N/A | asprof-only option designed for interactive use. It is a shortcut for running 3 actions: start, sleep for N seconds, stop. If no `start`, `resume`, `stop` or `status` option is given, the profiler will run for the specified period of time and then automatically stop.<br>Example: `asprof -d 30 <pid>` |
| `--timeout N` | `timeout=N` | The profiling duration, in seconds. The profiler will run for the specified period of time and then automatically stop.<br>Example: `java -agentpath:/path/to/libasyncProfiler.so=start,event=cpu,timeout=30,file=profile.html <application>` |
| `--loop TIME` | `loop=TIME` | Run profiler in a loop (continuous profiling). The argument is either a clock time (`hh:mm:ss`) or a loop duration in `s`econds, `m`inutes, `h`ours, or `d`ays. Make sure the filename includes a timestamp pattern, or the output will be overwritten on each iteration.<br>Example: `asprof --loop 1h -f /var/log/profile-%t.jfr 8983` |
| `-e --event EVENT` | `event=EVENT` | The profiling event: `cpu`, `alloc`, `nativemem`, `lock`, `cache-misses` etc. Use `list` to see the complete list of available events.<br>Please refer to [Profiling Modes](ProfilingModes.md) for additional information. |
| `-i --interval N` | `interval=N` | Interval has different meaning depending on the event. For CPU profiling, it's CPU time in nanoseconds. In wall clock mode, it's wall clock time. For Java method profiling or native function profiling, it's number of calls. For PMU profiling, it's number of events. Time intervals may be followed by `s` for seconds, `ms` for milliseconds, `us` for microseconds or `ns` for nanoseconds.<br>Example: `asprof -e cpu -i 5ms 8983` |
| `--alloc N` | `alloc=N` | Allocation profiling interval in bytes or in other units, if N is followed by `k` (kilobytes), `m` (megabytes), or `g` (gigabytes). |
@@ -40,12 +42,13 @@ The below options are `action`s for async-profiler and common for both `asprof`
| `--lock TIME` | `lock=TIME` | In lock profiling mode, sample contended locks whenever total lock wait time overflows the specified threshold. |
| `--nativelock TIME` | `nativelock=TIME ` | In native lock profiling mode, sample contended pthread locks (mutex/rwlock) whenever total lock wait time overflows the specified threshold. |
| `--wall INTERVAL` | `wall=INTERVAL` | Wall clock profiling interval. Use this option instead of `-e wall` to enable wall clock profiling with another event, typically `cpu`.<br>Example: `asprof -e cpu --wall 100ms -f combined.jfr 8983`. |
| `--proc INTERVAL` | `proc=INTERVAL` | Collect statistics about other processes in the system. Default sampling interval is 30s. |
| `--nobatch` | `nobatch` | Disable wall clock profiling optimization. Async-profiler will emit one `jdk.ExecutionSample` event for each wall clock sample instead of batching them in a custom `profiler.WallClockSample` event. |
| `-j N` | `jstackdepth=N` | Sets the maximum stack depth. The default is 2048.<br>Example: `asprof -j 30 8983` |
| `-L level` | `loglevel=level` | Log level: `debug`, `info`, `warn`, `error` or `none`. |
| `-F features` | `features=LIST` | Comma separated (or `+` separated when launching as an agent) list of stack walking features. Supported features are:<ul><li>`stats` - log stack walking performance stats.</li><li>`vtable` - display targets of megamorphic virtual calls as an extra frame on top of `vtable stub` or `itable stub`.</li><li>`comptask` - display current compilation task (a Java method being compiled) in a JIT compiler stack trace.</li><li>`pcaddr` - display instruction addresses .</li></ul>More details [here](AdvancedStacktraceFeatures.md). |
| `-f FILENAME` | `file` | The file name to dump the profile information to.<br>`%p` in the file name is expanded to the PID of the target JVM;<br>`%t` - to the timestamp;<br>`%n{MAX}` - to the sequence number;<br>`%{ENV}` - to the value of the given environment variable.<br>Example: `asprof -o collapsed -f /tmp/traces-%t.txt 8983` |
| `--loop TIME` | `loop=TIME` | Run profiler in a loop (continuous profiling). The argument is either a clock time (`hh:mm:ss`) or a loop duration in `s`econds, `m`inutes, `h`ours, or `d`ays. Make sure the filename includes a timestamp pattern, or the output will be overwritten on each iteration.<br>Example: `asprof --loop 1h -f /var/log/profile-%t.jfr 8983` |
| `-L level` | `loglevel=level` | Log level: `debug`, `info`, `warn`, `error` or `none`. |
| N/A | `log=FILENAME` | Dedicated file for log messages. Used internally by asprof. |
| N/A | `quiet` | Do not log "Profiling started/stopped" message. Used internally by asprof. |
| N/A | `server=ADDRESS` | Start insecure HTTP server with the given IP address/port to control the profiler. This option can be specified as `-agentpath` argument only. Be careful not to expose async-profiler server in a public network. |
| `--all-user` | `alluser` | Include only user-mode events. This option is helpful when kernel profiling is restricted by `perf_event_paranoid` settings. |
| `--sched` | `sched` | Group threads by Linux-specific scheduling policy: BATCH/IDLE/OTHER. |
| `--cstack MODE` | `cstack=MODE` | How to walk native frames (C stack). Possible modes are `fp` (Frame Pointer), `dwarf` (DWARF unwind info), `lbr` (Last Branch Record, available on Haswell since Linux 4.1), `vm`, `vmx` (HotSpot VM Structs) and `no` (do not collect C stack).<br><br>By default, C stack is shown in cpu, ctimer, wall-clock and perf-events profiles. Java-level events like `alloc` and `lock` collect only Java stack. |
@@ -55,7 +58,7 @@ The below options are `action`s for async-profiler and common for both `asprof`
| `--end function` | `end=FUNCTION` | Automatically stop profiling when the specified native function is executed. |
| `--ttsp` | `ttsp` | Time-to-safepoint profiling. An alias for `--begin SafepointSynchronize::begin --end RuntimeService::record_safepoint_synchronized`.<br>It is not a separate event type, but rather a constraint. Whatever event type you choose (e.g. `cpu` or `wall`), the profiler will work as usual, except that only events between the safepoint request and the start of the VM operation will be recorded. |
| `--nostop` | `nostop` | Record profiling window between `--begin` and `--end`, but do not stop profiling outside window. |
| `--libpath PATH` | `libpath=PATH` | Full path to `libasyncProfiler.so` (useful when profiling a container from the host). |
| `--libpath PATH` | N/A | Full path to `libasyncProfiler.so` (useful when profiling a container from the host). |
| `--filter FILTER` | `filter=FILTER` | In the wall-clock profiling mode, profile only threads with the specified ids.<br>Example: `asprof -e wall -d 30 --filter 120-127,132,134 Computey` |
| `--fdtransfer` | `fdtransfer` | Run a background process that provides access to perf_events to an unprivileged process. `--fdtransfer` is useful for profiling a process in a container (which lacks access to perf_events) from the host.<br>See [Profiling Java in a container](ProfilingInContainer.md). |
| `--target-cpu` | `target-cpu` | In perf_events profiling mode, instruct the profiler to only sample threads running on the specified CPU, defaults to -1.<br>Example: `asprof --target-cpu 3`. |
@@ -64,13 +67,14 @@ The below options are `action`s for async-profiler and common for both `asprof`
## Options applicable to JFR output only
| asprof | Launch as agent | Description |
| ------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--chunksize N` | `chunksize=N` | Approximate size for a single JFR chunk. A new chunk will be started whenever specified size is reached. The default `chunksize` is 100MB.<br>Example: `asprof -f profile.jfr --chunksize 100m 8983` |
| `--chunktime N` | `chunktime=N` | Approximate time limit for a single JFR chunk. A new chunk will be started whenever specified time limit is reached. The default `chunktime` is 1 hour.<br>Example: `asprof -f profile.jfr --chunktime 1h 8983` |
| `--jfropts OPTIONS` | `jfropts=OPTIONS` | Comma separated list of JFR recording options. Currently, the only available option is `mem` supported on Linux 3.17+. `mem` enables accumulating events in memory instead of flushing synchronously to a file. |
| `--jfrsync CONFIG` | `jfrsync[=CONFIG]` | Start Java Flight Recording with the given configuration synchronously with the profiler. The output .jfr file will include all regular JFR events, except that execution samples will be obtained from async-profiler. This option implies `-o jfr`.<br>`CONFIG` is a predefined JFR profile or a JFR configuration file (.jfc) or a list of JFR events started with `+`.<br><br>Example: `asprof -e cpu --jfrsync profile -f combined.jfr 8983` |
| `--all` | `all` | Shorthand for enabling `cpu`, `wall`, `alloc`, `live`, `nativemem` and `lock` profiling simultaneously. This can be combined with `--alloc 2m --lock 10ms` etc. to pass custom interval/threshold. It is also possible to combine it with `-e` argument to change the type of event being collected (default is `cpu`). This is not recommended for production, especially for continuous profiling. |
| asprof | Launch as agent | Description |
| ------------------- | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--chunksize N` | `chunksize=N` | Approximate size for a single JFR chunk. A new chunk will be started whenever specified size is reached. The default `chunksize` is 100MB.<br>Example: `asprof -f profile.jfr --chunksize 100m 8983` |
| `--chunktime N` | `chunktime=N` | Approximate time limit for a single JFR chunk. A new chunk will be started whenever specified time limit is reached. The default `chunktime` is 1 hour.<br>Example: `asprof -f profile.jfr --chunktime 1h 8983` |
| `--jfropts OPTIONS` | `jfropts=OPTIONS` | Comma separated list of JFR recording options. Currently, the only available option is `mem` supported on Linux 3.17+. `mem` enables accumulating events in memory instead of flushing synchronously to a file. |
| `--jfrsync CONFIG` | `jfrsync[=CONFIG]` | Start Java Flight Recording with the given configuration synchronously with the profiler. The output .jfr file will include all regular JFR events, except that execution samples will be obtained from async-profiler. This option implies `-o jfr`.<br>`CONFIG` is a predefined JFR profile or a JFR configuration file (.jfc) or a list of JFR events started with `+`.<br>Example: `asprof -e cpu --jfrsync profile -f combined.jfr 8983` |
| `--proc INTERVAL` | `proc=INTERVAL` | Collect statistics about other processes in the system. Default sampling interval is 30s. |
| `--all` | `all` | Shorthand for enabling `cpu`, `wall`, `alloc`, `live`, `lock`, `nativelock`, `nativemem`, and `proc` profiling simultaneously. This can be combined with `--alloc 2m --lock 10ms` etc. to pass custom interval/threshold. It is also possible to combine it with `-e` argument to change the type of event being collected (default is `cpu`). This is not recommended for production, especially for continuous profiling. |
## Options applicable to FlameGraph and Tree view outputs only
@@ -93,11 +97,14 @@ By default, async-profiler merges stack traces starting from the outermost (e.g.
| `-s --simple` | `simple` | Print simple class names instead of fully qualified names. |
| `-n --norm` | `norm` | Normalize names of hidden classes / lambdas. |
| `-g --sig` | `sig` | Print method signatures. |
| `-l --lib` | `lib` | Prepend library names to symbols, e.g. ``libjvm.so`JVM_DefineClassWithSource``. |
| `-a --ann` | `ann` | Annotate JIT compiled methods with `_[j]`, inlined methods with `_[i]`, interpreted methods with `_[0]` and C1 compiled methods with `_[1]`. FlameGraph and Tree view will color frames depending on their type regardless of this option. |
| `-l --lib` | `lib` | Prepend library names to symbols, e.g. ``libjvm.so`JVM_DefineClassWithSource``. |
| `--dot` | `dot` | Dotted class names, e.g. `java.lang.String` instead of `java/lang/String`. |
| `--samples` | `samples` | Count the number of samples. This is the default aggregation option. |
| `--total` | `total` | Count the total value of the collected metric instead of the number of samples, e.g. total allocation size. |
| `-I PATTERN` | `include=PATTERN` | Filter stack traces by the given pattern(s). `-I` defines the name pattern that _must_ be present in the stack traces. `-I` can be specified multiple times. A pattern may begin or end with a star `*` that denotes any (possibly empty) sequence of characters.<br>Example: `asprof -I 'Primes.*' -I 'java/*' 8983` |
| `-X PATTERN` | `exclude=PATTERN` | Filter stack traces by the given pattern(s). `-X` defines the name pattern that _must not_ occur in any of stack traces in the output. `-X` can be specified multiple times. A pattern may begin or end with a star `*` that denotes any (possibly empty) sequence of characters.<br>Example: `asprof -X '*Unsafe.park*' 8983` |
| N/A | `mcache[=AGE]` | Maximum age of the method name cache. Default is `0` (do not cache method names between profiling sessions). |
## Appendix

View File

@@ -177,7 +177,7 @@ public class AsyncProfiler implements AsyncProfilerMXBean {
/**
* Execute an agent-compatible profiling command -
* the comma-separated list of arguments described in arguments.cpp
* the comma-separated list of arguments defined in arguments.cpp
*
* @param command Profiling command
* @return The command result

View File

@@ -37,85 +37,7 @@ const size_t EXTRA_BUF_SIZE = 512;
// Parses agent arguments.
// The format of the string is:
// arg[,arg...]
// where arg is one of the following options:
// start - start profiling
// resume - start or resume profiling without resetting collected data
// stop - stop profiling
// dump - dump collected data without stopping profiling session
// status - print profiling status (inactive / running for X seconds)
// metrics - print profiler metrics in Prometheus format
// list - show the list of available profiling events
// version - display the agent version
// event=EVENT - which event to trace (cpu, wall, cache-misses, etc.)
// alloc[=BYTES] - profile allocations with BYTES interval
// tlab - use TLAB events for allocation profiling
// live - build allocation profile from live objects only
// nativemem[=BYTES] - profile native allocations with BYTES interval
// nofree - do not collect free calls in native allocation profiling
// trace=METHOD[:DURATION] - method to be traced with optional latency threshold
// lock[=DURATION] - profile contended locks overflowing the DURATION bucket (default: 10us)
// nativelock[=DURATION] - profile contended pthread locks overflowing the DURATION bucket (default: 10us)
// wall[=NS] - run wall clock profiling together with CPU profiling
// nobatch - legacy wall clock sampling without batch events
// proc[=S] - collect process stats (default: 30s)
// collapsed - dump collapsed stacks (the format used by FlameGraph script)
// flamegraph - produce Flame Graph in HTML format
// tree - produce call tree in HTML format
// jfr - dump events in Java Flight Recorder format
// jfropts=OPTIONS - JFR recording options: numeric bitmask or 'mem'
// jfrsync[=CONFIG] - start Java Flight Recording with the given config along with the profiler
// traces[=N] - dump top N call traces
// flat[=N] - dump top N methods (aka flat profile)
// otlp - dump in OpenTelemetry format
// samples - count the number of samples (default)
// total - count the total value (time, bytes, etc.) instead of samples
// chunksize=N - approximate size of JFR chunk in bytes (default: 100 MB)
// chunktime=N - duration of JFR chunk in seconds (default: 1 hour)
// timeout=TIME - automatically stop profiler at TIME (absolute or relative)
// loop=TIME - run profiler in a loop (continuous profiling)
// interval=N - sampling interval in ns (default: 10'000'000, i.e. 10 ms)
// jstackdepth=N - maximum Java stack depth (default: 2048)
// signal=N - use alternative signal for cpu or wall clock profiling
// features=LIST - advanced stack trace features (mixed, vtable, comptask, pcaddr)"
// safemode=BITS - disable stack recovery techniques (default: 0, i.e. everything enabled)
// file=FILENAME - output file name for dumping
// log=FILENAME - log warnings and errors to the given dedicated stream
// loglevel=LEVEL - logging level: TRACE, DEBUG, INFO, WARN, ERROR, or NONE
// quiet - do not log "Profiling started/stopped" message
// server=ADDRESS - start insecure HTTP server at ADDRESS/PORT
// filter=FILTER - thread filter
// threads - profile different threads separately
// sched - group threads by scheduling policy
// cstack=MODE - how to collect C stack frames in addition to Java stack
// MODE is 'fp', 'dwarf', 'lbr', 'vm' or 'no'
// clock=SOURCE - clock source for JFR timestamps: 'tsc' or 'monotonic'
// alluser - include only user-mode events
// fdtransfer - use fdtransfer to pass fds to the profiler
// target-cpu=CPU - sample threads on a specific CPU (perf_events only, default: -1)
// record-cpu - record which cpu a sample was taken on
// simple - simple class names instead of FQN
// dot - dotted class names
// norm - normalize names of hidden classes / lambdas
// sig - print method signatures
// ann - annotate Java methods
// lib - prepend library names
// mcache - max age of jmethodID cache (default: 0 = disabled)
// include=PATTERN - include stack traces containing PATTERN
// exclude=PATTERN - exclude stack traces containing PATTERN
// begin=FUNCTION - begin profiling when FUNCTION is executed
// end=FUNCTION - end profiling when FUNCTION is executed
// nostop - do not stop profiling outside --begin/--end window
// ttsp - only time-to-safepoint profiling
// title=TITLE - FlameGraph title
// minwidth=PCT - FlameGraph minimum frame width in percent
// reverse - generate stack-reversed FlameGraph / Call tree (defaults to icicle graph)
// inverted - toggles the layout for reversed stacktraces from icicle to flamegraph
// and for default stacktraces from flamegraph to icicle
//
// It is possible to specify multiple dump options at the same time
// The format of the string is: arg[,arg...]
Error Arguments::parse(const char* args) {
if (args == NULL) {
return Error::OK;

View File

@@ -54,6 +54,7 @@ static const char USAGE_STRING[] =
" -g, --sig print method signatures\n"
" -a, --ann annotate Java methods\n"
" -l, --lib prepend library names\n"
" --dot dotted class names\n"
" -o fmt output format: flat|traces|collapsed|flamegraph|tree|jfr|otlp\n"
" -I include output only stack traces containing the specified pattern\n"
" -X exclude exclude stack traces with the specified pattern\n"
@@ -77,6 +78,7 @@ static const char USAGE_STRING[] =
" --lock time lock profiling threshold in nanoseconds\n"
" --nativelock time pthread mutex/rwlock profiling threshold in nanoseconds\n"
" --wall interval wall clock profiling interval\n"
" --nobatch legacy wall clock sampling without batch events\n"
" --proc interval process sampling interval (default: 30s)\n"
" --all shorthand for enabling cpu, wall, alloc, live,\n"
" nativemem and lock profiling simultaneously\n"
@@ -501,9 +503,7 @@ int main(int argc, const char** argv) {
} else if (arg == "--width" || arg == "--height" || arg == "--minwidth") {
format << "," << (arg.str() + 2) << "=" << args.next();
} else if (arg == "--reverse" || arg == "--inverted" || arg == "--samples" || arg == "--total" ||
arg == "--sched" || arg == "--live" || arg == "--nofree" || arg == "--record-cpu" ||
arg == "--tlab") {
} else if (arg == "--reverse" || arg == "--inverted" || arg == "--samples" || arg == "--total") {
format << "," << (arg.str() + 2);
} else if (arg == "--alloc" || arg == "--nativemem" || arg == "--nativelock" || arg == "--lock" ||
@@ -512,14 +512,9 @@ int main(int argc, const char** argv) {
arg == "--target-cpu" || arg == "--proc") {
params << "," << (arg.str() + 2) << "=" << args.next();
} else if (arg == "--ttsp") {
params << ",ttsp";
} else if (arg == "--nostop") {
params << ",nostop";
} else if (arg == "--all") {
params << ",all";
} else if (arg == "--all" || arg == "--live" || arg == "--nobatch" || arg == "--nofree" || arg == "--nostop" ||
arg == "--record-cpu" || arg == "--sched" || arg == "--tlab" || arg == "--ttsp") {
params << "," << (arg.str() + 2);
} else if (arg == "--all-user") {
params << ",alluser";