blob: a751023b18429b75119fae9a957aa5c08303d48e [file] [log] [blame]
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=windows-1252">
<title>Java Application Profiling using TPTP</title>
<link rel="stylesheet" href="../default_style.css">
</head>
<body link="#0000ff" vlink="#800080">
<div align="right">&nbsp; <font face="Times New Roman, Times, serif"
size="2">Copyright &copy; 2006 International Business Machines Corp.</font>
<table border="0" cellpadding="2" cellspacing="0" width="100%">
<tbody>
<tr>
<td colspan="2" align="left" bgcolor="#0080c0" valign="top"><b><font
face="Arial,Helvetica"><font color="#ffffff">&nbsp;Eclipse Corner
Article</font></font></b></td>
</tr>
</tbody>
</table>
</div>
<div align="left">
<h1><img src="images/Idea.jpg" align="middle" height="86" width="120"></h1>
</div>
<p>&nbsp;</p>
<h3>Java Application Profiling using TPTP<br>
</h3>
<blockquote> <b>Summary</b> <br>
<br>
The Eclipse Test &amp; Performance Tools Platform (TPTP) Profiling tool
can be used to profile Eclipse plug-ins,
local Java(TM)
applications or complex applications running on multiple hosts and
different platforms.
The tool is tightly integrated with Eclipse, allowing profiling of
applications running from within Eclipse. <br>
This article demonstrates how
to use the TPTP Profiling tool to profile
a Java application for identifying execution related hot spots. It
shows
how to start the profiling session, use the various TPTP
views to analyze the data, identify methods with high execution time
then jump to the source code to fix the performance problem.<br>
<p><b> By Valentina Popescu, IBM<br>
<br>
</b> <font size="-1">February 21, 2006 (updated July 11, 2006)<br>
<br>
</font> </p>
</blockquote>
<hr width="100%"><br>
<h3>Profiling an Application<br>
</h3>
In the current environment of short development cycles for delivering a
product, developers tend to focus more on the functional aspects of
application execution, mostly via testing, debugging, and code fixing.
However, many problems do not easily surface until the application is
running in production mode, 24 hours a day, 7 days a week and gets
pushed to limits during some unexpected peak periods. <br>
<br>
The kinds of performance problems encountered in production cannot be
discovered during a
debugging
session. Before deployed and run in production mode, it is important to
use a Profiling tool to analyze application execution and identify
performance problems, such as execution
bottlenecks, object leaks, and system resource limitations.<br>
This article provides an introduction to the TPTP
Profiling
tool. It demonstrates how to use the TPTP Profiling tool to profile
a Java application in order to identify performance hot spots,
and fix and validate performance problems.<br>
<br>
<h3>TPTP Profiling Tool</h3>
The Eclipse Test &amp; Performance Tools Platform <a
href="http://eclipse.org/tptp/">(TPTP)</a> Project
offers a profiling tool for identifying and isolating performance
problems such
as performance bottlenecks, object leaks and system resource limits.
The tool
targets applications of all levels of complexity, from simple
standalone <span
style="font-size: 12pt; font-family: &quot;Times New Roman&quot;;">Java</span>
applications to Eclipse plug-ins or complex enterprise
applications running
on multiple
machines and on different platforms.
<br>
<br>
Being tightly integrated with the Eclipse project, the tool
is also easy to use and extend. That means that users can plug in their
preferred views to analyze the data, or can extend the data collection
metaphor
by implementing their own flavor of data collection agent.<br>
<br>
This article was written using the TPTP 4.2.0 based on the EMF 2.2.0
and
XSD 2.2.0 release builds, which require Eclipse 3.2.0. You can download
these drivers from <a
href="http://www.eclipse.org/tptp/home/downloads/downloads.php?link=link1&amp;ver=4.2.0">here</a>.
For TPTP 4.2.0 installation details go to the <a
href="http://www.eclipse.org/tptp/home/downloads/installguide/InstallGuide42.html">TPTP
download
page</a>.<br>
<br>
<br>
<h3>Profiling a Java application using TPTP<br>
</h3>
<div style="text-align: left;">The product catalog sample used in this
article
is a simple Java application that parses product
information stored in separate xml files and prints the result to the
console output. The file system location for the folder containing the
product xml files is passed as a program argument when running
the main class, <span style="font-style: italic;">Product.java</span>.
The xml files containing the product information are provided under the
section <a href="#RunningTheExample">running
the example</a>.<br>
<br>
<h4>Starting the application in profiling mode</h4>
After installing the sample application, the
first step is to run the product catalog application in profiling mode.
Profile
the application by using the <span style="font-style: italic;">Profile
As &gt; Java Application</span>
popup-menu on the Product class as seen in the image below. <br>
<br>
</div>
<div style="text-align: center;"><img alt=""
title="Profile the Product application"
src="images/n_profileAction.jpg" style="width: 699px; height: 603px;"><br>
<br>
</div>
<p style="text-align: center;"><b style="">Figure
1</b> Profile the <span style="font-style: italic;">Product catalog </span>Application<br>
<br>
</p>
<p style="text-align: left;"><img alt="" title="tip"
src="images/tip.gif" style="width: 62px; height: 13px;">Another way of
starting the application in profiling mode is to use the <span
style="font-style: italic;">Profile</span>
action available on the Java perspective's toolbar menu. Similar to
the
<span style="font-style: italic;">Run </span>and <span
style="font-style: italic;">Debug </span>toolbar actions, the <span
style="font-style: italic;">Profile </span>action will open the
launch configuration dialog and from there you can select the type of
application you want to profile.<br>
&nbsp;
<br>
</p>
<h4>Setting the Java program arguments</h4>
<p style="text-align: left;">The <span style="font-style: italic;">Profile
As &gt; Java Application </span>action will open the launch
configuration wizard as displayed by Figure 2.</p>
<p style="text-align: left;">For this example, the folder
containing the product xml files is passed as a program
argument. As described in the Figure 2 below, set the program arguments
to be <span style="font-style: italic;">x:\myPath\products</span>,
where <span style="font-style: italic;">x:\myPath </span>is the path
where you have unzipped the folder containing the product xml files
provided at the end of this article.<br>
</p>
<div style="text-align: center;"><img alt="Program arguments"
title="Program arguments" src="images/args.gif"
style="width: 591px; height: 585px;"><br>
<br>
<span style="font-weight: bold;">Figure 2</span> <span
style="font-style: italic;">Product catalog</span> sample - program
arguments<br>
</div>
<p style="text-align: left;"><span style="font-weight: bold;"></span></p>
<h4><br>
</h4>
<h4>Setting profiling filters</h4>
The next step is
to set the profiling options to collect method execution information.<br>
To set these options, click the Monitor tab on the Launch Configuration
Properties wizard and select a set of profiling options that fits with
your performance investigation.<br>
<br>
<img alt="" src="images/tip.gif" style="width: 62px; height: 13px;">A
Profiling filter set is a
reusable set of profiling filters.
The purpose of creating profiling filter sets is to reuse them
during consecutive runs of the same application or to share them
between applications that require the same type of profiling
information.<br>
The steps below describe how to create a new filter set used to
profile the Product catalog application. We will be creating a new
filter set named ProductFilterSet which will be used to profile only
packages that have the
<span style="font-style: italic;">com.sample.product</span> prefix.<br>
<br>
<p style="margin-left: 0.5cm; text-indent: -0.5cm;">1. Choose to
collect execution details by
selecting the Execution Time Analysis option in the Monitor tab. <br>
<br>
</p>
<div style="text-align: center;"><img
alt="Execution Time Analysis option"
title="Execution Time Analysis option" src="images/execOption.gif"
style="width: 542px; height: 490px;"><br>
</div>
<p style="text-align: center;"><b style="">Figure 3</b> Execution Time
Analysis option<br>
</p>
<p style="text-align: left;">As shown in Figure 3 above we have
selected the Execution Time Analysis option that can be used during
consecutive runs of the
product catalog application. On the next run of this application, the <span
style="font-style: italic;">Setting Profiling Filters</span> step can
be skipped.<br>
<br>
</p>
<p style="margin-left: 0.5cm; text-indent: -0.5cm;">2. Select Edit
Options action to set the profiling execution options.</p>
<p style="margin-left: 1cm; text-indent: -0.5cm;">2a. Select the
"Collect
boundary classes excluded by the filter set" option and enter 3 as the
Boundary class depth value. </p>
<p style="margin-left: 1cm;">By selecting this option, you specify that
you want to collect
information for methods invoked to the specified depth starting with
the methods in your filter criteria.</p>
<p style="margin-left: 1cm;">As an example, let's assume that we have
set
the filter to collect information on method MyMethod and to filter out
methods
M1, M2, M3, M4.</p>
<p style="margin-left: 1cm;">If the following invocation stack is
executed: MyMethod &gt; M1 &gt;
M2 &gt; M3 &gt; M4 ( MyMethod invokes M1 which invokes M2 which invokes
M3 which invokes M4 ), based on the filtering criteria selected at
point 2a, the profiler will show this call stack: MyMethod &gt;
M1 &gt; M2 &gt; M3 and will not display the last invocation M3 &gt; M4
(since this exceeds the specified depth of 3).</p>
<p style="text-align: center;"><img alt="Profiling Execution options"
title="Profiling Execution options" src="images/profOptions.gif"
style="width: 454px; height: 481px;"><br>
</p>
<p style="text-align: center;"><span style="font-weight: bold;">Figure 4</span>
Choose to collect execution information<br>
</p>
<br>
<p style="margin-left: 0.5cm; text-indent: -0.5cm;">3. Select the
classes to be profiled. <br>
</p>
<p style="margin-left: 0.5cm; text-indent: -0.5cm;">&nbsp;&nbsp;&nbsp;&nbsp;
In the Monitor tab, select the Java Profiling item and double click or
select Edit Options action. The Filter Set wizard opens.<br>
Use the Filter Set page to choose the classes you want to profile.
There are a set of predefined filters available but for this sample you
will create a new filter set named ProductFilterSet which filters out
everything except packages prefixed by com.sample.product.<br>
Follow these steps to create the filter set:<br>
</p>
<p style="margin-left: 1cm; text-indent: -0.5cm;">3a) Select the Add...
action from the filter set list. In
the result dialog enter ProductFilterSet as the name of the new filter
then click OK</p>
<p style="margin-left: 1cm; text-indent: -0.5cm;">3b) Use the Add...
button from the Contents of selected
filter set list to create the two filters as shown in Figure 5.</p>
<br>
<div style="text-align: center;"><img
alt="Select the classes to be profiled"
title="Select the classes to be profiled" src="images/n_pSetP3.jpg"
style="width: 627px; height: 568px;"><br>
<br>
<span style="font-weight: bold;">Figure 5</span> Choose classes you
want to profile<br>
</div>
<div style="text-align: center;"><br>
<div style="text-align: left;"><br>
<h4>Run the application</h4>
</div>
</div>
<br>
Run the Product catalog application by pressing OK on the Launch
Configuration
wizard. Choose Yes when asked to switch to the Profiling and Logging
perspective.<br>
You should see the result of the program execution in the Console view,
similar with what is presented in Figure 6 below. <br>
<br>
<br>
<div style="text-align: center;"><img
alt="Product application terminated"
title="Product application terminated" src="images/n_profileApp.jpg"
style="width: 753px; height: 600px;"><br>
<b style=""><br>
Figure 6</b> Product catalog application has been executed<br>
<br>
<br>
<div style="text-align: left;"><img alt="" src="images/tip.gif"
style="width: 62px; height: 13px;"> The TPTP profiling tool allows you
to
interact with your profiled application. You can pause and resume
monitoring, run garbage collection on the profiled application, collect
object references or terminate the application.<br>
</div>
</div>
<span style="font-weight: bold;"><br>
<br>
</span>
<h4>Identify performance hot spots using the Execution Statistics view</h4>
<br>
Use the Execution Statistics view to identify performance hot spots. To
open this view, select the&nbsp; process in the&nbsp; Profiling Monitor
view and select Open with &gt; Execution Statistics pop-up action.<br>
The Execution Statistic view shown in the Figure 7 below display the
methods executed, sorted by cumulative time. The cumulative time
for a method is the time spent to execute that method, including
any invocations to other methods.<br>
<br>
<br>
<div style="text-align: center;"><img alt="Execution statistics view"
title="Execution statistics view" src="images/n_executionStat.jpg"
style="width: 751px; height: 513px;"><br>
</div>
<div style="text-align: center;"><span
style="font-size: 12pt; font-family: &quot;Times New Roman&quot;;"></span><br>
<span style="font-size: 12pt; font-family: &quot;Times New Roman&quot;;"></span>
</div>
<p style="text-align: center;" class="MsoNormal"><b>Figure 7</b>
Execution
Statistics View<br>
</p>
As presented in Figure 4, the <b style="">Execution
Statistics</b> shows the main(java.lang.String[]),
readData(java.lang.String) and createParser() methods as the top three
methods with the highest execution time. It is not surprising to see
the main and readData methods on this list since the first one is the
starting point of the application execution while the second as
suggested by it's name, is reading the products data from the xml files.<br>
<br>
What comes as a surprise for us is the fact that createParser()
method, which
just creates a SAX parser instance used to parse
the xml files, has such a high execution time. The execution time for
this method accounts for 42.96% of
the application's total execution time. The Execution Statistics have
helped us to identify this method as a potential place to optimize the
application's performance.<br>
<br>
Once we have identified this, let's drill down and see the
createParser() method's execution details. <br>
<br>
<h4>Open Method Invocation Details view on the createParser() method<br>
</h4>
<br>
<div style="text-align: center;">
<div style="text-align: left;">We will use next the Method Invocation
Details view to see what methods in the createParser() call stack are
responsible for the method's slow execution time. Open the Method
Invocation Details view by double-click on the createParser() method in
the Execution Statistics view.<br>
<br>
<br>
<div style="text-align: center;"><img alt="Method Invocation Details"
title="Method Invocation Details" src="images/n_mInv.jpg"
style="width: 844px; height: 705px;"><br>
<br>
<span style="font-weight: bold;">Figure 8</span> Method Invocation
Details view<br>
</div>
</div>
<br>
</div>
<br>
Figure 8 below presents the execution information for the
createParser() method. As you can see the method has been invoked once
by the readData(java.lang.String) method and invokes 5 different
methods. In the invoked methods table you can see that newSAXParser()
and newInstance() methods are responsible for the createParser's method
slow execution. These two methods were called 24 times, as the
createParser() method has been executed 24 times.<br>
<br>
<h4>Define a solution for the identified performance problem<br>
</h4>
<br>
By analyzing this data, we found that one way to improve the
createParser() execution time is to improve the execution of the two
SAXParserFactory methods. Since we have no control over these methods'
implementation, the only way to improve our application execution is to
reduce the number of calls we make to these methods.<br>
<br>
The solution is to create one parser instance and reuse it for parsing
all xml files, instead of creating a new parser for every file. Let's
open the source code and apply the fix.<br>
<p style="text-align: left;"><img alt="" title="tip"
src="images/tip.gif" style="width: 62px; height: 13px;">Before making
any such optimizations, make sure that they are supported by the code.
For example, while the SAXParser cannot be simultaneously used by
multiple threads, instances can be reused. Strictly speaking, instances
should be <code>reset()</code>before they are reused. It is also a
good idea to have a comprehensive set of unit tests in place before you
make changes to code that could possibly introduce changes in behavior.</p>
<br>
<h4>Open the source code and apply the performance fix</h4>
To open the source code for the createParser() method, select the
method in the Method Invocation Details view then right-click and
choose the Open Source action on the pop-up menu.<br>
<br>
<br>
<br>
<div style="text-align: center;">
<div style="text-align: center;"><img alt="Source code"
title="Source code" src="images/n_sourceCode.jpg"
style="width: 815px; height: 693px;"><br>
</div>
<b><br>
Figure 9</b> Source code<br>
<br>
</div>
<p style="text-align: left;">Figure 9 shows the createParser() source
code. Notice that the method creates a new SAX parser instance on every
call.<br>
Update the source code as presented in Figure 10 below so that the code
will create only one parser instance and reuse it when parsing every
xml file.<br>
<br>
</p>
<p style="text-align: center;"><img alt="Source code"
title="Source code" src="images/n_sourceCodeFix.jpg"
style="width: 815px; height: 693px;"><br>
</p>
<p style="text-align: center;"><span style="font-weight: bold;">Figure
10 </span>Source code fix<br>
</p>
<p style="text-align: left;">As presented in Figure 10, the performance
fix defines a global SAXParser instance. The createParser() method
initializes the parser and returns this instance every time the method
is
called.<br>
</p>
<p style="text-align: left;">Let's go back now and validate the fix by
running the Product catalog application in profiling mode once again.<br>
<br>
</p>
<h4>Validate the performance fix<br>
</h4>
<p style="text-align: left;">To validate the performance fix, select
the Product&nbsp; class in the Java perspective and as described above,
right-click and choose Profile As &gt; Java Application.</p>
<p style="text-align: left;">The Profiling options wizard will not open
again as the previous profiling options will be used to run the
application. After the application is executed, open the Execution
Statistics view and compare the execution time.<br>
Figure 11 shows the execution times after the fix has been applied to
the code:<br>
</p>
<br>
<div style="text-align: center;">
<div style="text-align: center;"><img alt="Execution Statistics view"
title="Execution Statistics view" src="images/n_executionStatFix.jpg"
style="width: 742px; height: 575px;"><br>
</div>
<br>
</div>
<div style="text-align: center;"><b style="">Figure 11</b> Execution
Statistics view<br>
</div>
<p style="text-align: left;"><br>
</p>
As you can see in the image above, the createParser() execution time is
now only 19% of the application execution, while before the performance
fix has been applied to the code, the createParser() execution time was
almost 43% of the application execution time.<br>
Note that this improvement will prove to be even more valuable as the
number of xml files to be parsed increases, so the fix will reduce the
application execution time exponential as more product files are being
added to the catalog.<br>
<br>
<h3>Conclusion</h3>
This article has shown how the TPTP profiling tool can be used to
identify and solve performance problems. There are more aspects of the
TPTP tool not covered by this article. If you would like to know more
about the tool's capabilities, there are a set of&nbsp; tutorial slides
and User Guides available <a
href="http://www.eclipse.org/tptp/home/documents/index.html">here</a>.<br>
<br>
<h3><a name="RunningTheExample"></a>Running the example</h3>
The file "<a href="productCatalogSample.zip">ProductCatalog_example.zip</a>"
contains the complete source code for the example in this article.
Extract the content of the ZIP file into the Eclipse "plugins"
directory. You will also need the list of product xml files which are
stored in the <a href="xmlProductFiles.zip">products.zip</a> file.
Extract the
content of the products.zip file to a desired location on your file
system and use this path as a program argument when running the Product
catalog
application.<br>
<br>
<p><small>Java and all Java-based trademarks and logos are trademarks
or registered trademarks of Sun Microsystems, Inc. in the United
States, other countries, or both.<br>
<br>
</small></p>
<br>
<br>
</body>
</html>