InformIT

J2EE Performance Tuning, Part 2

Date: Mar 28, 2003

Article is provided courtesy of Sams.

Return to the article

Steven Haines details a robust tuning methodology that you can use to tune your J2EE applications and application servers. He describes the process of generating a load on your application server and lists what performance metrics you need to observe in your J2EE environment (as well as ways to get them).

Whether it is tuning a J2EE application, a database, or your own custom-built architecture, it is always best to start by defining the methodology that you will use, analyzing that methodology to ensure that it accurately solves your problem, and determining the requirements of that methodology. Although the first article in this series introduced you to J2EE performance tuning and the goals in tuning a J2EE environment, this article defines a tuning methodology you can use in your environment and the information you will need to apply this methodology.

Recall (from the previous article) that our goals in performance tuning are to maximize current users, throughput, and reliability through the systematic tuning of our application, application server, platform, and external dependencies.

Methodology Defined

I wish I could tell you that tuning a J2EE environment is as easy as adjusting a few parameters to specific values that I can list in one small table; unfortunately, it is far more complex and requires an intimate knowledge of your application as well as the way users will use your application. Figure 1 shows the entire tuning environment and methodology workflow graphically.

Figure 1Figure 1 Tuning methodology overview.


The first thing we need to look at is the user; we need to answer the following question: How will the user use my system? The answer will lead to a set of transactions that we can apply to the system (the term transaction in this context refers to a set of requests made by a user). Note that these transactions must be representative of expected end-user transactions because we will tune our system specifically to support these transactions!

Next, we need to generate these transactions inside the context of a load tester that can control such things as number of simultaneous users, think time, startup delay, and so on.

Once we have a load of users testing our application, we need to gather runtime performance metrics from the following sources:

And finally, once we have all of these metrics, we need to correlate, analyze, and present them.

Application

Each application is different: It has different steps that it walks through to service a user request, it has different interactions with back-end resources, and it has a different set of business requirements that it must satisfy. For example, consider an application that handles incoming purchasing requests over the Internet from a company's trading partners—the nature of its core transactions is to receive the incoming request, submit the request to the database, and return an acknowledgment. This is quite different from an e-commerce web site that is presenting a catalog of items for a user to purchase, maintaining a shopping cart, and processing credit card transactions.

The bottom line is that because these applications are different, they will use application server resources differently, which requires a different configuration. This is the most crucial step of the tuning process: understanding your business domain to define a set of representative transactions that accurately portray your true (or expected) end-user experience. If you do not do a good job here, you cannot expect good results once you open your doors for real-life users.

Load Testing

A load tester is an application that generates an arbitrary number of simultaneous user interactions with a system. There are several load testers on the market (see "Software Solutions" later in this article), but there is core functionality that each presents:

Most commercial load testers also provide you with a "learning" engine that will allow you to manually perform your transactions while it watches and records what you have done.

The goal of a load tester then is to simulate the real-life use of your application once you release it into a production environment. Without a representative load on your system, you cannot accurately tune it to support real-life users.

What Information is Needed?

At this point, we have a load tester generating a set of simultaneous users, each running transactions representative of our application usage. Now we need to gather runtime performance information from our application and application server, including the following:

The nature of which metrics to obtain and how to interpret them will be the focus of subsequent articles.

How is the Information Gathered?

For the purposes of this discussion, we focus on obtaining performance information for an application and an application server; hardware back-end resources are beyond our scope. Different application servers expose their runtime metrics differently, but in an attempt to standardize on one mechanism, Sun released the Java Management Extensions (JMX) interfaces. Although not completely adopted by all application server vendors, BEA WebLogic, IBM WebSphere version 5 and higher, and JBoss have all implemented JMX as their preferred management API and thus expose their configuration and runtime information via JMX. Other vendors have other proprietary ways of gathering this information, either through exposed Servlets or command-line tools.

Applications, on the other hand, are a bit more work. Although some application servers watch the performance of their applications and report some rudimentary performance information, by and large the preferred mechanism for obtaining this information is through code instrumentation. Code instrumentation can occur either inside the architecture of your application (for example, you write the code to monitor your application and expose it somehow to the world) or through a separate process that automatically instruments your code. Most commercial vendors have implemented code instrumentation that connects into the application server's class loader so that you do not have to do anything special with your application—just deploy it to an application server that has instrumentation installed, and its classes will be automatically instrumented upon creation.

The amount of information collected during code instrumentation is usually configurable and can be as limited as recording the response time of specific methods and as broad as recording every transaction sent to the application server. The difference and the trade off is the impact and overhead of the instrumentation on your system; more instrumentation equates to a higher overhead, and vice versa.

Correlation and Presentation

Once you have a simulated load of representative transactions running against your system and you have gathered runtime performance information from your application and application server, it is time to correlate that data and interpret what each metric means to your system's performance. The presentation of these metrics need only be as simple as plotting line graphs of one or more metrics at a time, but many of the commercial offerings provide very robust presentations—including graphical representations of call paths in trees and zooming capabilities. Many commercial offerings also provide preset views of runtime data that correlates different metrics that can be interpreted as a single indicator of a performance problem.

I will be dedicating significant time to the analysis and correlation of these metrics, the way the underlying subsystems operate, and how they affect your performance in subsequent articles.

Conclusion

Referring again to Figure 1, the following steps outline the tuning methodology:

  1. Load test your application using end-user representative transactions.

  2. Gather runtime performance information from your application and application server (and underlying platform, back-end resources, and so on).

  3. Observe the runtime performance and make changes as needed.

Tuning a J2EE environment is an iterative process: Start with a configuration that "looks good," load test the system, observe performance, change parameters, and start over. Recall that you want to pay particular attention to the concurrent user load and the transaction throughput of the system. (The greater the throughput, the better the performance.)

Software Solutions

This article referred to both load testers as well as J2EE monitors; this section defines several of the more popular products.

Load Testers

Monitoring/Diagnosis

Integrated Tuners

Unfortunately, there are not any integrated tuners that I am aware of. But...that leads to an open source project that my Microsoft-based programming counterpart and I have created for just that purpose! For all the updates, check http://etf.sourceforge.net. I will demonstrate it in many of the forthcoming application server-specific tuning articles.

Summary

In this article, we have identified the major components that comprise a tuning environment:

And we have defined how these can work together to tune a J2EE environment. Some of this might still be fuzzy because we have not discussed what metrics to monitor and how to interpret them, but don't worry: That understanding is the purpose of this series of articles.

Finally, we looked at some of the commercial and open source offerings to help us tune our environment.

What's Next?

In the next article, we will look at the architecture of a generic application server and answer the following question: What does an application server have to provide in order to be J2EE 1.3-compliant? These commonalities between the application server implementations will point to key tuning parameters.

800 East 96th Street, Indianapolis, Indiana 46240