Friday, May 14, 2010

Java CPU Usage Profiling

Recently I was working on a Java application that was pegging my CPU. Since this application was multi-threaded, I started looking for simple ways to determine which part of the application was the culprit. Since JConsole and VisualVM come bundled with Java 6 SDK I started looking at what they had to offer.

First we'll look at JConsole. Out of the box, JConsole provides a Threads tab that allows you to view what threads are running and generate a stack trace for a thread. It's essentially thread dumps with a GUI. It's not so useful for determining which threads are most active.

After a little more digging and I found a JConsole plugin called topthreads which is an enhanced version of the JTop plugin that ships with the JDK. For an overview of running topthreads, go here. You'll need to download the jar mentioned toward the bottom of the article and then fire up JConsole with the plugin:
jconsole -pluginpath /path/to/topthreads.jar 

The top threads plugin gives a much better view of the threads that are consuming the most CPU time:

Once you find a suspicious thread, you can switch back to the Threads tab in JConsole and get a stack trace of the thread. To really see what the thread is doing you'll likely need to take multiple snapshots of the thread and see what progress, if any, the thread is making.

Topthreads may help you find a rogue thread in a multithread application but it is not much help if you have a single threaded application that is performing poorly. Or perhaps you have a multithread application where several similar threads are taking up a large amount of cpu.

In my own debugging, I found that it wasn't the threads I cared about so much as the methods. Ultimately, you want to know which methods are taking up the most processing time. Enter VisualVM.

VisualVM contains a pretty impressive profiling tool that's easy to use. To get started with profiling with VisualVM, go here.

The profiler in VisualVM gives a nice view of top methods which can be sorted by time and invocations:

One downside to VisualVM's profiling is that it tanks the CPU when you first start profiling. The application your profiling will be limping for about 10 seconds while VisualVM digs in its profiling. It also adds a small bit of drag after profiling begins. By contrast, topthreads didn't add any noticable drag or hit on startup. Despite the performance penalty, I found VisualVM much better for profiling application performance.