📄 lib0123.html
字号:
<html>
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<head>
<title>Measuring Performance</title>
<link rel="STYLESHEET" type="text/css" href="images/xpolecat.css">
<link rel="STYLESHEET" type="text/css" href="images/ie.content.css">
</head>
<body>
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr><td><div STYLE="MARGIN-LEFT: 0.15in;"><a href="toc.html"><img src="images/teamlib.gif" width="62" height="15" border="0" align="absmiddle" alt="Team LiB"></a></div></td>
<td align="right"><div STYLE="MARGIN-LEFT: 0.15in;">
<a href="LiB0122.html"><img src="images/previous.gif" width="62" height="15" border="0" align="absmiddle" alt="Previous Section"></a>
<a href="LiB0124.html"><img src="images/next.gif" width="41" height="15" border="0" align="absmiddle" alt="Next Section"></a>
</div></td></tr></table>
<br>
<div class="chapter">
<a name="ch19"></a>
<div class="section">
<h2 class="first-section-title"><a name="600"></a><a name="ch19lev1sec1"></a>Measuring Performance</h2><p class="first-para">A load generator is a software package that measures the performance of applications, including J2EE applications. Typically, a load generator mimics multiple users so you can simulate load.</p>
<p class="para">Most load generators operate by running a test script (or a set of them) several times concurrently, simulating a configurable number of virtual users. By measuring the performance each virtual user gets, the load generator enables you to examine the performance averages over all virtual users. Sometimes this information is presented graphically.</p>
<p class="para">Load tests are usually written in the form of URL sequences. I prefer not to set up tests for other classes unless the application has significant back-end processing that needs to be tested under load. This can happen if your application processes JMS messages from other applications, for example.</p>
<p class="para">Although a load generator can tell you <i class="emphasis">if</i> you're meeting performance targets, it can't tell you <i class="emphasis">why</i> your performance is what it is. If you meet your performance targets, you should stop the tuning effort. If you don't meet your targets, you'll need to apply additional techniques to diagnose the causes of the performance problem.</p>
<p class="para">
<b class="bold">Use load tests to detect memory leaks in addition to performance.</b> Yes, even though Java has a garbage collector for memory, it's still possible to <a name="601"></a><a name="IDX-253"></a>have a leak. It's fairly easy to determine if you have a memory leak; it's much harder to find where it is.</p>
<div class="section">
<h3 class="sect3-title">
<a name="602"></a><a name="ch19lev2sec1"></a>Memory Leaks Defined</h3>
<p class="first-para">With Java, memory leaks occur in code that retains references to objects that are no longer needed. A <b class="bold">reference</b> is a variable declaration and assignment. Java's garbage collector periodically frees memory associated with nonreferenceable variables. If a variable is referenceable, its memory will not be freed.</p>
<p class="para">For instance, the variable <span class="fixed">account</span> in the following code is a reference for a value object:</p>
<div class="informalexample">
<pre class="literallayout">
AccountVO account = new AccountVO();
</pre>
</div>
<p class="para">If this line of code appears as a local variable declaration within a method, the reference ends when the method completes. After the method completes, the garbage collector frees memory associated with the <span class="fixed">account</span> declaration.</p>
<p class="para">If the declaration is an instance-level field, the reference ends when the enclosing object is no longer referenced. For example, if the variable <span class="fixed">account</span> is declared as an instance-level field for <span class="fixed">CustomerVO</span>, the reference to account ends when the reference to an instantiated <span class="fixed">CustomerVO</span> object ends, as shown here:</p>
<div class="informalexample">
<pre class="literallayout">
public class CustomerVO
{
private AccountVO account = new AccountVO();
}
</pre>
</div>
<p class="para">A variable defined as <span class="fixed">static</span> can easily cause a memory leak because the reference ends when the JVM stops or the reference is specifically nulled out.</p>
<p class="para">
<b class="bold">Memory leaks in J2EE applications are frequently caused by statically defined </b><b class="bold"><span class="fixed">Collection</span></b> <b class="bold">objects.</b> For instance, it's common to statically define an application <span class="fixed">Properties</span> object to store configuration details, as in the following:</p>
<div class="informalexample">
<pre class="literallayout">
public class Environment
{
private static Properties _configurationProps =
new Properties();
}
<a name="603"></a><a name="IDX-254"></a>
</pre>
</div>
<p class="last-para">Any value stored in this statically defined <span class="fixed">Properties</span> object is referenceable. <span class="fixed">Collection</span> objects, such as <span class="fixed">Properties</span> or <span class="fixed">HashMaps</span>, often produce memory leaks because it's easy to put values into them and forget to remove them later.</p>
</div>
<div class="section">
<h3 class="sect3-title">
<a name="604"></a><a name="ch19lev2sec2"></a>Testing for Memory Leaks</h3>
<p class="first-para">To test for memory leaks, note how much memory the container is using before, during, and after the test. You should see memory at a low level to start, ramp up during the test, and slowly decrease within a few minutes to an hour after the test. For example, a container might initially start at 128MB of memory and grow to 180MB during the performance test. After the test, memory allocation should trend back toward 128MB.</p>
<p class="para">It's not realistic for memory to return to its pretest level, but most of the memory allocated during the test should be freed. To diagnose memory leaks, I start by running the test in a profiler with the memory options turned on. The <a href="LiB0124.html#609" target="_parent" class="chapterjump">next section</a> tells you how to do this.</p>
<p class="para">One output of memory leak testing is knowing which transactions are not performing to requirements. In the layered application architecture discussed in this book, the business logic layer or the data access layer are the most likely places for performance problems to occur. Beans and Web services usually only publish functionality in business objects anyway. It should be relatively quick to construct a test case (or modify an existing one) specifically for the underlying business objects that produce the performance problem. Constructing these test cases gives you something that's easier to profile.</p>
<p class="para">I use an open source load generator from Apache called JMeter. It's easy to install and set up test plans. You can obtain JMeter at <a target="_top" class="url" href="http://jakarta.apache.org/jmeter/">http://jakarta.apache.org/jmeter/</a>. A JMeter test plan can contain a thread group with any number of URLs. You dictate how many "virtual users" get created to run the test plan and how long they run. If you set up a URL for each major page and control in your application, you'll get average, minimum, and maximum timing information for each URL, as illustrated in <a class="internaljump" href="#ch19fig01">figure 19.1</a>. JMeter allows you to save this information in a separate file for future reference later.</p>
<div class="figure">
<a name="605"></a><a name="ch19fig01"></a><span class="figuremediaobject"><a href="images/fig271%5F01%5F0%2Ejpg" NAME="IMG_45" target="_parent"><img src="images/fig271_01.jpg" height="262" width="350" alt="Click To expand" border="0"></a></span>
<br style="line-height: 1">
<span class="figure-title"><span class="figure-titlelabel">Figure 19.1: </span>JMeter Example</span>
</div>
<a name="606"></a><a name="IDX-255"></a>
<p class="para">
<b class="bold">Always run load tests under the same conditions multiple times.</b> You need to make sure that nothing is interfering with the test that you're not aware of. I've seen load tests accidentally contending for batch runs or server back-ups. If you run each test at least twice and get similar results each time, then you'll have a higher degree of trust in the information JMeter gives you.</p>
<p class="para">
<b class="bold">Document and limit changes between each test.</b> If you make several changes between load tests, you won't know which of the changes helped or hurt performance. For example, let's say you changed four things. It's possible that one of the changes helped performance, one of the changes hurt performance, and two didn't make any material difference whatsoever. Because you combined the changes, however, you'll never really know what helped performance and what hurt it.</p>
<p class="para">
<b class="bold">Monitor and record CPU and memory usage during the test.</b> The simplest way to do this is at the operating system level. Most UNIX operating systems provide a <span class="fixed">top</span> utility, which provides CPU and memory usage for each <a name="607"></a><a name="IDX-256"></a>process as well as usage for the entire server. You're obviously interested in what's happening for the container process during the load test. <a class="internaljump" href="#ch19list01">Listing 19.1</a> is an extract from a <span class="fixed">top</span> utility output. If your application runs on a Windows platform, you'll need to use the <span class="fixed">perfmon</span> utility.</p>
<div class="example">
<span class="example-title"><span class="example-titlelabel">Listing 19.1: </span>Sample Top Utility Output</span><a name="608"></a><a name="ch19list01"></a>
<div class="formalbody">
<table class="BlueLine" border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td bgcolor="000080" class="bluecell"><font size="2" face="Arial" color="010100"><b><img src="_.gif" width="1" height="2" alt="Start example" border="0"></b></font></td>
</tr>
</table>
<pre class="literallayout">
PID USER PRI NI SIZE RSS SHARE STAT <b class="bold">%CPU %MEM</b> TIME COMMAND
21886 dashmore 15 0 1012 1012 776 R <b class="bold">0.1 0.1</b> 0:00 java
1 root 15 0 480 480 428 S <b class="bold">0.0 0.0</b> 0:04 init
2 root 15 0 0 0 0 SW <b class="bold">0.0 0.0</b> 0:00 keventd
3 root 15 0 0 0 0 SW <b class="bold">0.0 0.0</b> 0:00 kapmd
</pre>
<table class="BlueLine" border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td bgcolor="000080" class="bluecell"><font size="2" face="Arial" color="010100"><b><img src="_.gif" width="1" height="2" alt="End example" border="0"></b></font></td>
</tr>
</table>
<table class="BlankSpace" border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td height="16"></td>
</tr>
</table>
</div>
</div>
<p class="para">It's more convenient to limit <span class="fixed">top</span> utility output to the process running the container. Unfortunately, the options to the <span class="fixed">top</span> utility are different for each platform. For instance, on Solaris, using the <span class="fixed">–U</span> option will limit output to a specific user.</p>
<div class="informalexample">
<pre class="literallayout">
top –U username
</pre>
</div>
<p class="para">On Linux, you would limit output by specifying the process ID with the <span class="fixed">–p</span> option.</p>
<div class="informalexample">
<pre class="literallayout">
top –p pid
</pre>
</div>
<p class="para">If you're using a UNIX other than Solaris or Linux, you'll have to consult the manual page for the <span class="fixed">top</span> utility for your specific UNIX platform. By the way, <a href="LiB0125.html#628" target="_parent" class="chapterjump">Loukides (2002)</a> is an excellent reference for interpreting CPU and memory utilization statistics that UNIX utilities provide.</p>
<p class="last-para">Expect to see both CPU and memory usage increase during the test and decrease after the test. If you don't see memory allocation diminish after the test (e.g., within fifteen to thirty minutes), it's likely that you have a memory leak. You should profile your load test both for CPU usage and memory usage.</p>
</div>
</div>
</div><br>
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr><td><div STYLE="MARGIN-LEFT: 0.15in;"><a href="toc.html"><img src="images/teamlib.gif" width="62" height="15" border="0" align="absmiddle" alt="Team LiB"></a></div></td>
<td align="right"><div STYLE="MARGIN-LEFT: 0.15in;">
<a href="LiB0122.html"><img src="images/previous.gif" width="62" height="15" border="0" align="absmiddle" alt="Previous Section"></a>
<a href="LiB0124.html"><img src="images/next.gif" width="41" height="15" border="0" align="absmiddle" alt="Next Section"></a>
</div></td></tr></table>
</body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -