How to Profile Clojure Code

22 May 2015  —  Torsten Becker

I had some trouble to find a straight answer on how to profile a Clojure application to find CPU hotspots. After some searching and tinkering, I ended up with these steps that worked for me:

1. Download, install, and launch VisualVM. VisualVM is definitely good enough for basic profiling. If you want more detail, you might want to give YourKit a try. You'll have to pay a license for YourKit, though.

2. Add the following to your Leiningen project.clj file. Either in a profile or on the top level:

:jvm-opts ["-Dcom.sun.management.jmxremote"
           "-Dcom.sun.management.jmxremote.ssl=false"
           "-Dcom.sun.management.jmxremote.authenticate=false"
           "-Dcom.sun.management.jmxremote.port=43210"]

This will enable Java Management Extensions (JMX) for the Clojure JVM process. VisualVM uses these extensions to profile the JVM process. The port 43210 is arbitrary, pick what you like.

3a. If you are running the Clojure application on local host continue with step 6.

3b. If the Clojure application is running on a remote host:

4. Connect to the remote host and open a SOCKS proxy with ssh:

ssh remote_host -D 9191

This will allow VisualVM to connect to JMX on the remote host. Strangely, just forwarding a single port (with -L) has not worked for me. Apparently VisualVM needs more than one connection.

5. Enable SOCKS proxy in VisualVM

On Mac OS X, go to VisualVMPreferences.... Then select the Network tab in the VisualVM app.

Enable Manual proxy settings; then set the SOCKS Proxy: to localhost with port 9191.

Change the No Proxy hosts to local, *.local, 169.254/16, *.169.254/16, localhost, *.localhost.

It is important that 127.0.0.1 is not part of that list.

Preferences Screen Shot

6. Attach to the running Clojure process:

Go to FileAdd JMX Connection...

Enter 127.0.0.1:43210 as the Connection.

Add JMX Connection Screen Shot

7. Start profiling

Select the Sampler tab and click the CPU button.

Profiling Screen Shot

Happy optimizing!