Skip to content

Repository files navigation

A tool to turn the output of -XX:+TraceBytecodes (a JDK debug-only feature to print every bytecode executed by the interpreter) into a simple stack format, and a script to turn that into flame graphs showing what happened during program execution, bytecode-by-bytecode: Flame graph generated from running a Hello World program on 9-ea+157

Who/what is this for?

This is a diagnostic tool I've developed and used to visualize what is going on at startup at a high granularity. Since it relies on a very verbose and slow debug option it's not by any means a good estimator of how long time things actually take.

As such, this is more a diagnostic tool than a profiler, but a tool that has served us well to disentangle various startup dependencies and inefficiencies in the JDK itself - and been a valuable aid in diagnosing a number of startup regressions.

Why?

Most profiling tools either have a blind spot when it comes to capturing what happens during the very early initialization of a JVM, e.g., agent based instrumentation, JFR etc, or they are native profiling tools that would attribute everything to "something in the interpreter".

Requirements

  • Perl is required to run FlameGraph.
  • Git and access to GitHub are required on the first run unless FlameGraph is already present in the FlameGraph directory next to the bytestacks launcher.
  • a fastdebug (recommended) or slowdebug build of OpenJDK

Usage

  • Build: ./gradlew build
  • With a fastdebug build of java, run any (small) program with -XX:+TraceBytecodes -XX:+IgnoreUnrecognizedVMOptions -XX:+TraceBytecodesTruncated, e.g.: java -XX:+TraceBytecodes -XX:+IgnoreUnrecognizedVMOptions -XX:+TraceBytecodesTruncated HelloWorld | ./bytestacks helloworld
    • On first use the launcher clones FlameGraph into ./FlameGraph if not already present.
    • This generates helloworld.stacks and helloworld.svg only.
  • Open helloworld.svg in your favorite SVG viewer. A modern web browser should suffice.

Bundling for offline use

To build a distributable intended to run without GitHub access you must include the FlameGraph checkout alongside the launcher:

git clone --depth 1 https://github.com/brendangregg/FlameGraph.git FlameGraph

The resulting layout must contain both ./bytestacks and ./FlameGraph/flamegraph.pl.

Going deeper...

  • To get the full picture of what's going on, especially on a longer running program, it can be enlightening to run your program with -Xint, since as things start to get compiled they will disappear from view.
  • For performance reasons there is a granularity option which allows setting a threshold for how small methods are output in the stack output, defaulting to 25. By setting this to a lower value, the generated flame graph will become more detailed, but may also become very heavy to render.

References

About

Turn -XX:+TraceBytecodes output into a FlameGraph compatible stack format

Resources

Stars

48 stars

Watchers

4 watching

Forks

Releases

Packages

Used by

Contributors

Languages