# Converter Usage

async-profiler provides `jfrconv` utility to convert between different profile output formats.
`jfrconv` can be found at the same location as the `asprof` binary. Converter is also available
as a standalone Java application: [`jfr-converter.jar`](https://github.com/async-profiler/async-profiler/releases/latest/download/jfr-converter.jar).

## Supported conversions

The tool can convert several source formats into various outputs. The conversion capabilities are summarized below:

| Source format | to html | to collapsed | to pprof | to pb.gz | to heatmap | to otlp |
| ------------- | ------- | ------------ | -------- | -------- | ---------- | ------- |
| jfr           | ✅      | ✅           | ✅       | ✅       | ✅         | ✅      |
| html          | ✅      | ✅           | ❌       | ❌       | ❌         | ❌      |
| collapsed     | ✅      | ✅           | ❌       | ❌       | ❌         | ❌      |

## Usage

```
jfrconv [options] <input> [<input>...] <output>
```

The output format specified can be only one at a time for conversion from one format to another.

```
Conversion options:
  -o --output FORMAT, -o can be omitted if the output file extension unambiguously determines the format, e.g. profile.collapsed

  FORMAT can be any of the following:
  # collapsed: This is a collection of call stacks, where each line is a  semicolon separated
               list of frames followed by a counter. This is used by the FlameGraph script to
               generate the FlameGraph visualization of the profile data.

  # html: FlameGraph is a hierarchical representation of call traces of the profiled
          software in a color coded format that helps to identify a particular resource
          usage like CPU and memory for the application.

  # pprof: pprof is a profiling visualization and analysis tool from Google. More details on
           pprof on the official github page https://github.com/google/pprof.

  # pb.gz: This is a compressed version of pprof output.

  # heatmap: A single page interactive heatmap that allows to explore profiling events
             on a timeline.

  # otlp: OpenTelemetry profile format.

Differential Flame Graph:
  --diff <base-profile> <new-profile>

JFR options:
    --cpu              Generate only CPU profile during conversion
    --cpu-time         Generate only CPU profile, using CPUTimeSample events
    --wall             Generate only Wall clock profile during conversion
    --alloc            Generate only Allocation profile during conversion
    --live             Build allocation profile from live objects only during conversion
    --nativemem        Generate native memory allocation profile
    --leak             Only include memory leaks in nativemem
    --tail RATIO       Ignore tail allocations for leak profiling (10% by default)
    --lock             Generate only lock contention profile during conversion
    --nativelock       Generate only native (pthread) lock contention profile
    --trace            Convert only MethodTrace events
 -t --threads          Split stack traces by threads
 -s --state LIST       Filter thread states: runnable, sleeping, default. State name is case insensitive
                       and can be abbreviated, e.g. -s r
    --classify         Classify samples into predefined categories
    --total            Accumulate total value (time, bytes, etc.) instead of samples
    --lines            Show line numbers
    --bci              Show bytecode indices
    --simple           Simple class names instead of fully qualified names
    --norm             Normalize names of hidden classes/lambdas, e.g. Original JFR transforms
                       lambda names to something like pkg.ClassName$$Lambda+0x00007f8177090218/543846639
                       which gets normalized to pkg.ClassName$$Lambda
    --dot              Dotted class names, e.g. java.lang.String instead of java/lang/String
    --from TIME        Start time in ms (absolute or relative)
    --to TIME          End time in ms (absolute or relative)
                       TIME can be:
                       # an absolute timestamp specified in millis since epoch;
                       # an absolute time in hh:mm:ss or yyyy-MM-dd'T'hh:mm:ss format;
                       # a relative time from the beginning of recording;
                       # a relative time from the end of recording (a negative number).
    --latency MS       Retain only samples within MethodTraces of at least MS milliseconds

Flame Graph options:
    --title STRING     Convert to Flame Graph with provided title
    --minwidth X       Skip frames smaller than X%
    --grain X          Coarsen Flame Graph to the given grain size
    --skip N           Skip N bottom frames
 -r --reverse          Reverse stack traces (defaults to icicle graph)
 -i --inverted         Toggles the layout for reversed stacktraces from icicle to flamegraph
                       and for default stacktraces from flamegraph to icicle
 -I --include REGEX    Include only stacks with the specified frames, e.g. -I 'MyApplication\.main' -I 'VMThread.*'
 -X --exclude REGEX    Exclude stacks with the specified frames, e.g. -X '.*pthread_cond_(wait|timedwait).*'
    --highlight REGEX  Highlight frames matching the given pattern
```

See the [profiler options documentation](ProfilerOptions.md#options-applicable-to-flamegraph-and-tree-view-outputs-only) for details on the `--reverse` and `--inverted` options.

## jfrconv examples

`jfrconv` utility is provided in `bin` directory of the async-profiler package.
It requires JRE to be installed on the system.

### Generate Flame Graph from JFR

If no output file is specified, it defaults to a Flame Graph output.

```
jfrconv foo.jfr
```

Profiling in JFR mode allows multi-mode profiling. So the command above will generate a Flame Graph
output, however, for a multi-mode profile output with both `cpu` and `wall-clock` events, the
Flame Graph will have an aggregation of both in the view. Such a view wouldn't make much sense and
hence it is advisable to use JFR conversion filter options like `--cpu` to filter out events
during a conversion.

```
jfrconv --cpu foo.jfr

# which is equivalent to:
# jfrconv --cpu -o html foo.jfr foo.html
```

for HTML output as HTML is the default format for conversion from JFR.

### Flame Graph options

To add a custom title to the generated Flame Graph, use `--title`, which has the default value `Flame Graph`:

```
jfrconv --cpu foo.jfr foo.html -r --title "Custom Title"
```

### Differential Flame Graph

To find performance regressions, it may be useful to compare current profile
to a previous one that serves as a baseline. Differential Flame Graph
visualizes such a comparsion with a special color scheme:

- Red color denotes frames with more samples comparing to the baseline (i.e. regression);
- Blue is for frames with less samples;
- Yellow are new frames that were absent in the baseline.

The more intense the color, the larger the delta.
For each different frame, the delta value is displayed in a tooltip.

![](/.assets/images/flamegraph_diff.png)

Differential Flame Graph takes the shape of the current profile:
all frames have exactly the same size as in the normal Flame Graph.
This means, frames that exist only in the base profile will not be visible.
To see such frames, create another differential Flame Graph,
swapping the base and the current input file.

To create differential Flame Graph, run `jfrconv --diff` with two input files:
basline profile and new profile. Both files can be in JFR, HTML, or collapsed format.
Other converter options work as usual.

```
jfrconv --cpu --diff baseline.jfr new.jfr diff.html
```

Output file name is optional. If omitted, `jfrconv` takes the name
of the second input file, replacing its extension with `.diff.html`.

## Standalone converter examples

Standalone converter jar is provided in
[Download](https://github.com/async-profiler/async-profiler/?tab=readme-ov-file#Download).
It accepts the same parameters as `jfrconv`.

Below is an example usage:

```
java -jar jfr-converter.jar --cpu foo.jfr --reverse --title "Application CPU profile"
```
