Performance tuning is a complex area, and the factors that affect performance are sometimes out-side the application itself. These factors may include the network configuration and hardware platform characteristics, the operating system settings, Java virtual machine parameters, database tuning parameters, and finally the architecture of the Web application itself.
Recommended approach of performance tuning:
1. Set up a test bed.
2. Do performance testing. Use the results of your first test run as a performance benchmark or baseline for subsequent testing.
3. Investigate performance bottlenecks in your application, deployment environment, and other systems that it interacts with.
4. Identify areas where improvements are needed; these might involve implementation changes as well as deployment or configuration tuning of your Web application.
5. Make one fix.
6. Repeat steps 2 through 5.
Step 1: Set Up a Test Bed
Create a mirror of production with application and database. All performance related test will be occurred in this test bed.
Step 2: Test Performance and Identify the Baseline
Before you start performance tuning in earnest, measure how the system is performing currently. Developing a good plan for performance testing is important. Some considerations while developing test
plans are as follows:
- Use automated performance test tools.
- The test traffic generated should mirror the expected traffic on the Web site as much as possible.
- Send test traffic to cover as many paths through your application as feasible, and send HTTP requests with different request parameters.
- Test with the extremes.
- Test over longer periods.
Step 3: Diagnose Performance Bottlenecks
Next, identify your performance bottlenecks. Performance issues can be diagnosed in a number of ways:
❏ Instrument your application with log messages, or profile it to determine where it spends most
of its time.
❏ Use any performance tuning tools supplied by your database vendor to identify performance
problems.
❏ Use the tools provided by your operating system to look at the CPU, memory, and I/O usage
characteristics of your application. These can often give you a clue about what the root cause of
the performance issue is.
Some of the useful Linux tools that you can use to examine the system resource usage include:
❏ top: Displays the top CPU-intensive processes.
❏ vmstat: Reports on virtual memory, as well as statistics on processes, and disk and CPU activity.
❏ free: A snapshot of the free and used memory on your system.
❏ sysstat: A family of tools available from http://perso.orange.fr/sebastien.godard/
index.html. These include the iostat tool that reports on CPU and I/O statistics.
Diagnosing Tomcat Performance Issues
Diagnosing issues with Tomcat can be very tricky. It gets easier when there is an indication about what is
causing the problem in the Tomcat logs, such as:
- Tomcat freezes or pauses with no requests being processed: Tomcat could be doing a lot of garbage collection. Set the -verbose:gc flag for the JVM and observe from the log file if this is indeed the case. If so, tune the JVM parameters, such as -Xms and -Xmx.
- OutOfMemory exceptions in the Tomcat logs: This can occur for a number of reasons: A memory leak in your application: Run a profiler to see if this is the case. The maximum heap memory is less: Use the -Xmx option to increase it.
- Too much memory has been allocated: For example, you should not set your maximum heap size to be the same or very close to your system RAM. Your OS uses a certain per-cent of the RAM, and if the -Xmx value is set too high, Java can take this memory fromyour swap disk. This will slow down Tomcat significantly, and you might also see an OutOfMemory exception if you run out of swap.
- Tomcat caches the JSP content generated: If your generated JSP pages are very huge, the result may be OutOfMemory exceptions as the cached response fills up the heap. Set the org.apache.jasper.runtime.JspFactoryImpl. USE_POOL and org.apache.jasper.runtime.BodyContentImpl.LIMIT_BUFFER to false to fix this.
- The JDK has built-in mechanisms to help debug pesky out-of-memory errors: For instance, Sun’s JDK has an option called -XX:-HeapDumpOnOutOfMemoryError that, asthe name suggests, writes out the heap memory dump when there is an OutOfMemory exception. This .hprof file can then be read by profiling tools to help debug the problem.
- The OutOfMemoryError: PermGen space errors sometimes occur if you run multiple Web applications in single Tomcat instance, or if your application loads up a lot of classes. The JVM allocates a 64MB memory chunk for the permanent generation heap, which is the heap that holds objects such as classes and methods. When this space gets exceeded, you start getting the PermGen space errors. You would need to increase this setting: Use the -XX:MaxPermSize option in Sun’s JDK to increase the permanent generation heap space. This is explained in more detail in the section “Tuning the JVM Parameters” later in the chapter.
Tomcat Performance Tuning Tips
Broadly, factors that affect performance can be addressed at three stages: at design time, at development time, and at deployment time. Decisions made at design time often have the greatest impact on performance. The design includes both the software as well as the system architecture. The software architecture is concerned with issues such as design of software modules, data structures, and so on. The system architecture, on the other hand, would also address issues such as the following:
❏ How will your software components be deployed?
❏ Is there load balancing to handle a large volume of requests?
❏ Are there clustering/failover capabilities to handle situations when a Web server or any other component of the Web site goes down?
The development time issues relate to how the Java code for the Web application was designed and implemented. Again, there is a whole set of implementation best practices surrounding this area, such as:
❏ Do not create sessions for JSPs if they are not required.
❏ Do not store large objects in your session.
❏ Time out sessions quickly, and invalidate your sessions when you are done with them.
❏ Use the right scope for objects.
❏ Use connection pooling for improving performance.
❏ Cache static data.
❏ Use transfer objects to minimize calls to remote services.
❏ Minimize logging from Web applications, or use simple logging formats.
Tuning the JVM Parameters
There are two different virtual machines inside the binary that’s executed to start Java applications: the client VM and the server VM. Each of these two VMs is optimized according to the needs of client and server applications. The server VM can be selected by passing the -server command-line option to the Java VM on startup. This can be done by setting the JAVA_OPTS variable in the Tomcat startup script.
The minimum and maximum heap size can be increased through Xms and Xmx parameter.
These, and other options, can be passed to the JVM running Tomcat by modifying the <TOMCAT_HOME>/catalina.sh (or catalina.bat ) file, and adding the following line (as an example) in the beginning of the file.
On Linux:
JAVA_OPTS=”$JAVA_OPTS -Xms512m -Xmx1024m”
On Windows:
SET JAVA_OPTS=%JAVA_OPTS% -Xms512m -Xmx1024m
An important option for Sun’s JVM is the -XX:MaxPermSize option. This is used to specify the size permanent generation heap, which is the heap that holds objects such as classes and methods.
Turning Off JSP Reload and JSP Development Mode
The two attributes that control the JSP compilation behavior in Tomcat are development and reloading . If you don’t want the JSP pages to be checked for modification each time there is a request, you should set development to false . In the following settings, the reloading attribute is also set to false . Had reloading been true , background compiles would have been enabled. The background compile option causes the container to check and compile JSPs after a period of time. Another configurable parameter, called checkInterval decides how frequently the compiles are triggered. In the current Tomcat default setting, both development and reloading are set to true , and checkInterval is set to 300 seconds.
Open the (<Tomcat Home>/conf/web.xml) file and edit the initial parameters like this:
<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
<init-param>
<param-name>fork</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>development</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>reloading</param-name>
<param-value>false</param-value>
</init-param>
…
</servlet>
Turning On Custom Tags Pooling
The following is an excerpt from the global Web application deployment descriptor ( <Tomcat
Installation Directory>/conf/web.xml ) that has defaults for all the Web applications. The settings are for the JspServlet , which handles all requests for JSP pages. The enablePooling attribute specifies whether pooling of tag library classes is to be enabled ( true ) or not ( false ). If this setting is missing, it defaults to true .
<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
<init-param>
<param-name>fork</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>enablePooling</param-name>
<param-value>true</param-value>
</init-param>
…
</servlet>
Turning Off Web Application Auto-Deploy and Reloading
By default, Tomcat monitors the <TOMCAT_HOME>/webapps directory for new Web applications, and as soon as a WAR file is copied there, it gets automatically deployed. While this auto-deploy feature is great for development environments, it has a performance impact and should be disabled in production. To turn off auto-deploy in Web applications, edit the server.xml file and set the autoDeploy attribute in the appropriate Host to false , as shown here:
<Host name=”localhost” appBase=”webapps” unpackWARs=”true”
autoDeploy=”false”
xmlValidation=”false” xmlNamespaceAware=”false”>