NetBeans IDE 4.0 Profiler Tutorial
This article was submitted as part of the Win With NetBeans contest. The author's name will be added at the conclusion of the competition.
The NetBeans Profiler is a powerful tool that provides important information about
the runtime behavior of your application. While imposing relatively little overhead,
the NetBeans Profiler tracks CPU performance and memory usage.
This tutorial will show you how to use the Profiler with NetBeans 4.0 to:
Portions of this tutorial originally appeared in a June, 2004 Java Developer's Journal
article about JFluid,
the underlying technology used by the NetBeans Profiler. All reprinted material is used
by permission of the publisher of Java Developer's Journal.
This tutorial should take approximately one hour to complete.
NetBeans IDE 4.0 Quick Start Guide for Web Applications
Starting with NetBeans 4.0 or Java for the first time?
See the
NetBeans IDE 4.0 Quick Start Guide for Web Applications.
Once you have completed it, you will be ready to build on your knowledge with this
tutorial!
Setting Up Your Environment
Installing the Profiler
The NetBeans Profiler is in beta and is available as a separate download.
To use this tutorial you must install the most recent version of the NetBeans
Profiler. Be sure to follow the NetBeans Profiler
Download & Install instructions.
Configuring Tomcat
Profiling a web application requires that the web server be run with
the JVM that is included with the NetBeans Profiler. So to use
the NetBeans Profiler with the Tomcat server
a small change to the Tomcat startup script is necessary in order to set
JAVA_HOME correctly. In addition, you must
"expand" the JVM provided with the NetBeans Profiler by adding folders to it from
a v1.4.2 JDK.
Obtaining the required source files
This tutorial uses a web application based on the
HelloWeb project created in the
NetBeans IDE 4.0 Quick Start Guide for Web Applications. The modifications
for this tutorial include the addition of a servlet that handles the
incoming request. It creates a Java bean and then dispatches to the JSP
that creates the response. The servlet has been poorly written on purpose in order
to highlight features of the NetBeans Profiler.
You get all application files from the ProfilingTutorial.zip file.
- In your file system, create a folder for the unzipped application files. From now on,
this folder will be referred to as $UNZIPHOME.
- Click here
to download the ProfilingTutorial.zip file.
- Use an application that unzips files to unzip the ProfilingTutorial.zip
file to $UNZIPHOME.
$UNZIPHOME now has web and src folders. The
web folder contains the two JSP files and the deployment descriptors. The
src folder contains the source files for the servlet and Java bean classes.
Creating a Project
Monitoring Runtime Behavior
Attaching to a Running Application
Now that you have verified that Tomcat is using the JVM included with the NetBeans
Profiler you can attach the IDE's profiling tools to that JVM and monitor its runtime
behavior.
- Determine the process ID of the JVM that is running Tomcat. The list of processes
that are running java.exe should have grown by one since you last listed them in the
Running the Project step. The new java.exe process
is the one that was added to run Tomcat. Make a note of its process ID.
- Choose Profile > Attach Profiler. In Working Directory type the fully
qualified name of Tomcat's bin folder. As an example, a typical value on
a Windows system would be:
C:\Program Files\netbeans-4.0\nb4.0\jakarta-tomcat-5.0.28\bin
And on Unix the value will be something like:
/export/home/gs/tools/netbeans/40/nb4.0/jakarta-tomcat-5.0.28/bin
- Click the Monitor Application button. Make sure that the Enable Threads
Monitoring option is not checked.
- Click the Attach button. Select Manually enter PID of the application. In PID
type in the process ID of the JVM that is running Tomcat. Click the OK button.
The NetBeans Profiler displays three graphs in the output pane, as illustrated below.
The graph on the left is the easiest to understand. The red shading indicates the allocated
size of the JVM heap, updated approximately once per second. The purple
overlay indicates the amount of heap space actually in use. In the example above the
allocated heap size at the last update was almost 14 megabytes. Of that 14 megabytes
a little over 4 megabytes is actually being used to hold Java objects.
The graph on the right is also easy to understand. It merely shows the count of active
threads in the JVM, updated approximately once per second.
The graph in the center is the most interesting. It shows two important heap
statistics.
- The blue line is the percentage of execution time spent by
the JVM doing garbage collection and is graphed against the y-axis on the right
edge of the graph. Time spent by the JVM doing garbage collection is time that is
not available for it to run your application. So if the blue line indicates a large
percentage you may want to consider tuning the JVM by configuring a larger heap
size (refer to the -Xmx parameter
documentation)
or perhaps switching to a different garbage collection
algorithm.
-
The red line is surviving generations and is graphed against the y-axis scale
on the left edge of the graph. The count of surviving generations is the number of different
ages of all the Java objects on the JVM's heap, where "age" is defined as the number of
garbage collections that an object has survived. When the value for surviving generations is low it
indicates that most of the objects on the heap have been around about the same amount of time.
If, however, the value for surviving generations is increasing at a high rate over time then it
indicates your application is allocating new objects while maintaining references to many
of the older objects it already allocated. If those older objects are in fact no longer
needed then your application is wasting (or "leaking") memory.
Clicking the
button will
cause the IDE to display larger versions of the three graphs in the main display pane.
Determining CPU Time Used by a Method
Switching to Performance Analysis Mode
The Profiler is attached to the Tomcat JVM, but is only monitoring high level statistics. To
find out detailed information about the performance of a specific method (or methods) in
the application you will need to modify the Profiler's settings.
- Click the
button or
choose Profile > Modify Profiling.
- Click the Analyze Performance button.
- Select the Part of Application radio button. Then click the
Select button that is next to the Part of Application radio button.
- Click the Add button.
- Click the Select button. The Profiler displays the Select Class tree.
- Expand the Source Packages entry by clicking its plus sign icon.
- Expand the org.me.hello entry.
- Expand the RequestHandler.java entry.
- Click the RequestHandler entry and then click the OK button.
- The methods in the RequestHandler class are now displayed in the Select Methods dialog
as illustrated below. Click the processRequest method and then click the OK button.

- Select the processRequest method by clicking on it in the list of
Root Methods and then click the OK button.
You have just selected processRequest as the root method for performance analysis. This means
that the processRequest method and all methods that it calls, and all methods that they
in turn call (and so on) will be monitored. Starting
from processRequest, the
Profiler does analysis of the method call graph to determine which methods need profiling.
Only those methods are profiled - the rest of your application will continue to run at full
speed with no profiling overhead.
- Click the OK button on the Modify Profiling dialog.
Running the Profiled Method
Now that you have chosen processRequest as a root method you need to use the
portion of the web application that causes that root method to run. This is easy to do
because the processRequest method handles all requests from the index.jsp page.
- In your web browser click the Back button to return to the
http://localhost:8084/ProfilingTutorial/ page.
- Click the OK button to resubmit "NetBeans User" as your user name. It will take a bit
longer before the response appears because the Profiler is monitoring performance of the
processRequest method.
- After Hello, NetBeans User! displays in your browser, click the
button or
choose Profile > Get Current Results.
Interpreting the Performance Analysis Graphs
The Profiler displays the latest performance results, as illustrated below.
The top window shows the complete method call graph beginning with the root method.
The processRequest method ran for 168 milliseconds (ms). Note, however, that very
little time was spent running the instructions of the processRequest method itself -
the sixth line in the window shows the "self time" for processRequest to be only 0.421 ms.
The vast majority of the time was spent in methods called by processRequest. In particular,
the forward method took up 84.7% of the execution time. This is not surprising
given the amount of work the forward method has been given to do.
The power of the NetBeans Profiler is it helps you identify bottlenecks in your code
that were not expected or that will prevent your application from scaling well.
Note that the createUniqueID method took up 11.3% of the execution time. You can
click the plus sign next to the createUniqueID entry to investigate exactly where
the time went. If you
examine the source code for createUniqueID you will discover it uses a hideously
inefficient algorithm that should be redesigned.
The bottom window is a flatter depiction - it shows the "self time" for each
method in the call graph.
Monitoring the Creation of Objects
Switching to Memory Analysis Mode
The Profiler can do detailed analysis (also referred to as instrumentation) of CPU performance or memory
usage, but it cannot do both at the same time. To
find out detailed information about the allocation and garbage collection of
objects on the JVM's heap you will need to modify the Profiler's settings.
- Click the
button
or choose Profile > Modify Profiling.
- Click the Analyze Memory Usage button.
- Select the Record both object creation and garbage collection radio button.
- Click the OK button.
Running the Profiled Application
Now that you have chosen analyze memory usage you need to use the
web application in order to determine whether it is using memory efficiently.
- In your web browser click the Back button to return to the
http://localhost:8084/ProfilingTutorial/ page.
- Click the OK button to resubmit "NetBeans User" as your user name.
- After Hello, NetBeans User! displays in your browser, click the browser's Back button
to return to the previous page.
- Repeat steps 2 through 3 nine times. Repeated submission of the same user name is
necessary for this demonstration.
- Click the
button or
choose Profile > Get Current Results.
- The Profiler displays the latest memory analysis results in a table. Click
the Class Name column to sort the rows by class name.
- Scroll down through the table rows until the row for the
org.me.hello.NameHandler class is displayed.
Interpreting the Memory Analysis Graphs
The illustration below shows the statistics for the org.me.hello.NameHandler class.
The columns provide object allocation and memory usage information.
- Total alloc. obj. (on the far right) is easiest to understand. This is the total count
of all objects of this class that have been created. For the NameHandler class this value is
10, which is the number of times you pressed the Ok button on the web application's form.
- Allocated Objects is the number of objects that the Profiler is actually monitoring.
In this example, of the 10 instances of NameHandler that have been created
the Profiler is only monitoring 1 of those instances.
By default
this number will be approximately ten percent of the value of total allocated objects (so the
numbers you see might vary a bit from the illustration). By monitoring
only a subset of the created objects the Profiler is able to dramatically reduce the overhead
it places on the JVM, which then allows your application to run at close to full speed.
- Live Objects is the number of the Allocated Objects that are still on the JVM's heap and
are therefore taking up memory.
- The two Live Bytes columns show the amount of heap memory being used by the Live Objects.
One column displays a graph, the other displays text.
- The Age Average value is calculated using the Live Objects. The age of each object is the number
of garbage collections that it has survived. The sum of the ages divided by the number
of Live Objects is the Age Average.
- The Generations value is calculated using the Live Objects. As with Age Average, the
age of an object is the number of garbage collections it has survived. The Generations value
is the number of different ages for the Live Objects.
You can use this information to help track down memory leaks. The value for Generations
is the same as the Surviving Generations value described in the Interpreting the
Monitor Graphs section, but restricted to the objects of a single class. This finer granularity
of monitoring can help you find the specific objects that are wasting heap space.
In this example,
though, you do not even need Generations to see a problem with the NameHandler class. The Total
alloc. obj. value is 10. The intent of the servlet code was to reuse NameHandler objects
when the same user name is entered. Clearly, that is not happening. The bug is in the
processRequest method: the key used to check for an entry in the Map is not
the same as the key used to store the entry. The result is a pretty typical Java memory
leak: an object is placed into a Map and then forgotten.
Another handy tool for understanding application behavior is to see where in your code
the objects of a particular class are being allocated. This can often provide clues about
why an object is still on the heap. The NetBeans Profiler will display stack traces for any
class if you right-click the class's entry in the table and choose Show Allocations Stack Traces.
To end the profiling session, choose Profile > Detach.
Exploring Further
Refer to the NetBeans Profiler help file for more information on these topics.
- When profiling CPU usage a class filter can be defined to prevent the profiling
of methods outside your application (for example all methods in java.*). This helps keep your application
running at closer to full speed.
- The Analyze Memory Usage feature can be limited to monitoring just object allocation.
This will decrease the Profiler's impact on performance.
- If when analyzing memory usage you discover that only a few classes seem to be
causing problems, you can disable the monitoring of objects of all other classes.
- Features are available that will monitor your application's startup time
or a specific code fragment in your application.
- Detailed thread statistics are available.