Liking cljdoc? Tell your friends :D

clj-async-profiler CircleCI

clj-async-profiler is an embedded high-precision performance profiler for Clojure. Embedded means there is no software to install on your system, instead you add the profiler to your application as a dependency. From there, you can operate the profiler either programmatically or via a web UI. During profiling, clj-async-profiler has very low overhead, so it is suitable for usage even in highly loaded production scenarios.

clj-async-profiler presents the profiling results as an interactive flamegraph. You can navigate the flamegraph, query it, change parameters and adapt the results for easier interpretation.

Example flamegraph. Click to open the interactive version.

To collect the profiling data, clj-async-profiler utilizes async-profiler which is a low overhead sampling profiler for Java. Current version of async-profiler that is used by clj-async-profiler is 2.8.2.

Usage

clj-async-profiler is only supported on GNU/Linux and MacOS. On Linux, you need to allow async-profiler to use kernel profiling data by setting these two variables (see also):

sudo sysctl -w kernel.perf_event_paranoid=1
sudo sysctl -w kernel.kptr_restrict=0

Next, add com.clojure-goes-fast/clj-async-profiler to your dependencies. This is the latest version:

JDK11+: you must start your application with JVM option -Djdk.attach.allowAttachSelf, otherwise the profiling agent will not be able to dynamically attach to the running process. For Leiningen, add :jvm-opts ["-Djdk.attach.allowAttachSelf"] to project.clj. For tools.deps, add the same :jvm-opts to deps.edn or write -J-Djdk.attach.allowAttachSelf explicitly in your REPL command.

clj-async-profiler.core exposes an all-in-one facade for generating profiling flame graphs. The most common usage scenario looks like this:

(require '[clj-async-profiler.core :as prof])

;; Profile the following expression:
(prof/profile (dotimes [i 10000] (reduce + (range i))))

;; The resulting flamegraph will be stored in /tmp/clj-async-profiler/results/
;; You can view the HTML file directly from there or start a local webserver:

(prof/serve-files 8080) ; Serve on port 8080

You can also start and stop the profiler manually with prof/start and prof/stop.

Each profiling command accepts a map of options. See docstrings for each command for the list of supported options.

Option map for each profiling command can have a :pid value. If it is provided, an external JVM process with this PID will be sampled, otherwise the current process is targeted.

For a detailed description of clj-async-profiler's more advanced features, check the following blog posts:

Extra tuning

From async-profiler README: It is highly recommended to use -XX:+UnlockDiagnosticVMOptions -XX:+DebugNonSafepoints JVM flags. Without those flags the profiler will still work correctly but results might be less accurate. Without these options, there is a high chance that simple inlined methods will not appear in the profile. When agent is attached at runtime, CompiledMethodLoad JVMTI event enables debug info, but only for methods compiled after the event is turned on.

If you see stackframes like /usr/lib/.../libjvm.so, it means that you have to install JDK debug symbols. E.g., on Ubuntu that would be the package openjdk-11-dbg.

Platform support

clj-async-profiler ships with the precompiled native libraries that async-profiler itself distributes. These include:

  • Linux: x64, x64 with musl libc (Alpine), aarch64 (arm64)
  • MacOS: x64/aarch64 (universal binary)

To use clj-async-profiler on other supported platforms, you should do the following:

  1. Build async-profiler for the desired platform.

  2. Put the resulting libasyncProfiler.so in a place accessible by your JVM process (and which also allows code execution from).

  3. Execute from Clojure:

    (reset! clj-async-profiler.core/async-profiler-agent-path
            "/path/to/libasyncProfiler.so")
    

License

async-profiler is distributed under Apache-2.0. See APACHE_PUBLIC_LICENSE file. The location of the original repository is https://github.com/jvm-profiling-tools/async-profiler.

Copyright 2017-2022 Andrei Pangin


clj-async-profiler is distributed under the Eclipse Public License. See ECLIPSE_PUBLIC_LICENSE.

Copyright 2017-2022 Alexander Yakushev

Can you improve this documentation?Edit on GitHub

cljdoc is a website building & hosting documentation for Clojure/Script libraries

× close