Java Profiling with MonkeyWrench
MonkeyWrench GUI Overview
The configuration screen of MonkeyWrench (see Figure 1) displays the controls for the other screens of MonkeyWrench. The “CPU & Memory Profiling” section controls the operation of the “CPU” and “Memory” tabs; the “Thread Profiling” section controls the operation of the “Threads” tab, and the “Garbage Collection Profiling” section controls the “Garbage Collection” tab. Note that only the CPU and Memory profiling involve bytecode injection, the most expensive operations in the profiler; Thread and Garbage Collection profiling use JMX beans only, and so have much less impact on the performance of your target application. The right side of this screen is a help document which contains an abbreviated version of the information in this article.
CPU and Memory profiling are turned on or off at the same time, so those two tabs are linked by one configuration. Considering this as one feature, this feature, thread profiling and garbage‐collection profiling are independent features that can be turned on or off individually. If an application is undergoing heavy garbage collection, for example, MonkeyWrench can be used to profile just the garbage collection without the additional overhead of method profiling.
To avoid leaving a target application with expensive profiling code injected, the “close” button of MonkeyWrench is disabled while CPU and memory profiling is active. To re‐enable this button, you must stop CPU and memory profiling, from the Configuration tab.
The following sections will focus on each of the remaining tabs of the application by feature. Since all of these features are available in some form in most profilers, each feature section will include a discussion of the motivation behind the specific features provided by MonkeyWrench.
Configuration is split into three areas, as described earlier. Each is covered in the following subsections.
CPU & Memory Profiling
CPU & Memory profiling is defined as the injection of bytecode to notify MonkeyWrench when methods or constructors are entered and exited. When one of these events occurs, the collected information includes system time and the current thread’s CPU time, as well as its stack trace.
The constructors and methods chosen for profiling are determined by a Java regular expression. Before you build this regular expression, you must first decide if you want the expression to define class names or method names. If you match on class names, all visible constructors and methods will be instrumented for each class that matches. If you match on method or constructor names, your regular expression must match exactly on that method or constructor. The match expression includes the full package name of the class. If you don’t want to type out the full package of a class, you can start the regex with “.*” as a shortcut, although you may end up matching more than you intended. You can also specify an exclusion regular expression; if it is specified, it takes precedence over inclusions.
For example, if you want to instrument all methods starting with “get” in the class com.example.Printer, your regular expression could be com.example.Printer.get.* and you would choose “Instrument on Method/Constructor Name”. If you want to instrument every method in the same class, you would choose “Instrument on Class Name” and give the regular expression com.example.Printer. Note that the dot “.” character actually means “match any character”, so the above expressions should actually escape the dot to match specifically on that character (e.g. com\.example\.Printer), but in practice the lazy regex will usually match just what you want. Just be aware that it might match more than you expect.
The regex window does live validation of your expression as you are typing it, to warn you of incorrectly formulated regular expressions. In these cases, the text is colored red and the tool tip tells you what the problem is. Note that the validation is aggressive and will flag an expression that might eventually be correct when you are done typing it (for example, when you are entering an escape character, or have not yet completed typing a correct sequence of characters). Figure 3 shows an example of what you would see if you were about to escape an open‐parenthesis, where your eventual regex will be “.*\(“. Validation occurs on each keystroke, so entering a “(“ after the “\” will return the display to the “valid” state.
You can specify multiple regular expressions in each window by separating them with a comma. Note that everything between commas is considered part of the regular expression! If you follow a comma with a space character and then some non‐whitespace characters, you are specifying an additional regex which starts with a space character.
Figure 3 -- Regular Expression Feedback
The update interval defaults to 5 seconds. This means that every 5 seconds, MonkeyWrench will process the data structures of method‐entry and method‐exit calls, calculate wall clock times and CPU times, and update the MonkeyWrench CPU and Memory tabs. While the collection of profiling data if fairly expensive, the updating of the display is also quite expensive. Note that a lot of activity must occur on the AWT event thread, to avoid concurrency issues with the GUI’s data structures, so there will be a noticeable impact on the performance of the MonkeyWrench and the target application when the screens are updated. If in addition you are profiling a Swing application, the update pause becomes even more noticeable. For this reason, unless you are profiling a rather narrow slice of classes in your application, it is recommended that you start with a display update interval of 30 seconds.
The “Clear CPU and Memory Data on Start/Stop” checkbox is designed to help you narrow down profiling data to specific windows of time, and to separate profiling results for one set of classes (per the regular expressions you specify) from results for a different set of classes. One strength of MonkeyWrench is the ability to clear data on demand (so, for example, you can clear profiling data just before initiating an expensive operation in your target application). This checkbox is another way of isolating profiling results.
Since bytecode injection itself is an expensive operation, a progress bar runs both when classes are being instrumented and when they are being restored to their original state. During profiling, you can click on the “View Instrumented Classes” (or “View Instrumented Methods”, depending on which instrumentation choice you have made) to verify that you instrumented the classes or methods that you specified in your regular expressions.
As was mentioned earlier, once profiling is turned on, the “close” button on MonkeyWrench is disabled. This step is taken to prevent the profiler from being disposed while the target application is still instrumented. To re‐enable the MonkeyWrench “close” button, stop CPU and Memory profiling.
For more discussion of the actual profiling data collected and displayed during this type of profiling, see the section “CPU & Memory Profiling”.
Thread profiling configuration is relatively simple; all you need to decide is how often the display updates (this interval is independent of the CPU & Memory Profiling interval) and whether or not you want thread profiling data to be cleared on start and stop. MonkeyWrench maintains records of all threads it has seen during profiling; clearing profiling data (either via the “…Now” button or at profiling start and stop) clears memory of threads which are no longer running. Note, however, that there is some data which isn’t cleared; for example, the cumulative CPU time of a thread is retrieved from the Thread JMX bean and will include CPU time accumulated before the last time the MonkeyWrench display was cleared. A good recommended update interval here is one second.
For more discussion of the data collected and displayed for thread profiling, see the section “Thread Profiling”.
Garbage Collection Profiling
The configuration options for garbage‐collection profiling are similar to those for thread profiling. The recommended (and default) display‐update interval is five seconds, although it can be set as low as one second. You can also specify whether or not to clear data on profiling start and stop.
A discussion of the data displayed in garbage‐collection profiling, and the motivation for the MonkeyWrench displays, can be found in “Garbage Collection Profiling”.
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)