Wednesday, March 5, 2008

Debugging and Profiling - same, not different

Why is it that Eclipse has such a great debugger, but such a extremely poor profiler?

I've used JProfiler and YourKit Profiler, and find both products interesting (however, JProfiler gets my money). However, they are a just that slight tad too awkward to fire up - I don't use them often enough, so it is not "in the fingers" in the same way I always run my programs through the Eclipse debugger.

The Eclipse profiler, when I've gotten it to work, which is a real PITA, is amazingly slow - I've never been able to profile even the simplest applications. I wonder if it doesn't use some XML format to transfer the profiling information from the profiled application to the profiler..

The Eclipse debugger, on the other hand, is a truly wonderful tool - for what it is made for.

Then, one suddenly starts to wonder: aren't these two things pretty much the same stuff? Both the debugger and the profiler needs to be able to inspect the objects on heap, control threads, inspect stacks. This has been recognized by the JVM vendors, where the two JVM interfaces, JVMPI (JVM Profiling Interface) and JVMDI (JVM Debugger Interface), have been unified into the JVMTI (JVM Tools Interface). So why aren't simply these two JVM tools indeed a unified power tool?

I've so many times wanted to just stop the application and check out what all the memory is used for right now - "Heap Walking" in JProfiler terminology. Or just do a quick analyze of where the CPU is being used from here on to there on, using for example two breakpoints. There are plenty other scenarios where the features of a debugger and a profiler overlap, and where just one of them doesn't quite cut it. Starting the JVM with both JProfiler and Eclipse attached actually seems to work in some fashion (as long as you don't pause JProfiler's handling threads, as the JProfiler GUI then freezes), but I always seem to get Threads in the debugger that when paused, don't give me the stack, but instead show "", causing Eclipse to pretty much freeze too, and it is hardly the perfect situation at any rate.

Here's some possibilities:

  • Take a heap snapshot at some certain breakpoint.

  • Pausing the application, then taking a "heap walking tour". Resume, then exercise the application by doing that thing that always messes up. Pause again, snapshot, compare difference (or use breakpoints instead of manual pauses).

  • Stepping the application, having one thread in pause. Make a heap snapshot of all objects that the current thread's stack points to, displaying it graphically along with the stack trace, arrows pointing out from each stack element.

  • .. and being able to expand a Thread's stack elements and view the actual variables that hold on to each part of the heap graph, visually using arrows pointing to the objects

  • When in "heap walking", have a more direct understanding of what threads hold on to what objects.

  • Start allocation recording and/or cpu recording (start profiling) when any thread reaches some breakpoint.

  • Do timing analysis (profiling) of a single thread between two breakpoints. Do this repeatedly while the application is being exercised, and aggregate.

  • By default pause the application at a OutOfMemoryError and do a heap snapshot.

  • (Admittedly only a profiling wish:) Like YourKit (unlike JProfiler), let heap snapshots be "full" (include the data) and standalone, with thread stack information, in that the entire heap is dumped to disk, so that it is possible to easily compare.

Basically - what I want is the integration of the features that a debugger has, and what a profiler has. In particular the combination of stack-inspection from the debugger with heap-inspection from the profiler, and the code-integrated features with breakpoints and exception-breakpoints that a debugger has (the now standard fully integrated IDE debugger), triggering the profiling and heap snapshotting features that a profiler typically has.

I think that if these JVM inspection tools wasn't made with one or the other application in mind but instead thought of as one unified unit, a much more powerful tool would emerge. (I nearly get that tech-drool when thinking of how cool it would be: "so, I believe this object should go out of scope at this breakpoint.. So, why isn't it GC-able now? Lets trace-to its GC roots..").

Now, I have understood that Netbeans have a much more integrated profiler than Eclipse. I really should check Netbeans out someday very soon..!