Struts2 Performance Testing

Important Note: The following results are obtained when HTTP monitor process is enabled on NetBeans. Disabling this monitor process substantially improves response times. I will update this post with revised metrics soon.

I recently did  performance testing on the latest version of Struts2 framework (2.2.3.1). I wanted to see how many requests a simple Struts2 application can handle on a single Tomcat instance. I also wanted to check whether there are any major performance issues with Struts 2 framework.

The simple Struts 2 application I developed was hosted on Tomcat 7 server from the NetBeans IDE. I used JMeter on a separate machine to simulate the load.  The performance test was done in two phases,

Load Testing (Phase 1) – Struts2 application was hosted on NetBeans IDE with Tomcat 7. JMeter was run on a separate machine and performance metrics were collected from JMeter and Windows 7 Performance Monitor. In this phase I wanted to see what is the maximum concurrent user load that could be applied without considerable degradation in response time.

Performance Profile (Phase 2) – Struts2 application was hosted on NetBeans IDE with Tomcat 7. NetBeans code profiler was attached to the Tomcat session. JMeter was run on a separate machine and performance metrics were collected from JMeter, Windows 7 Performance Monitor and NetBeans Profiler.  In this phase I was looking for any obvious bottlenecks in the Struts2 framework.

Sample Struts2 Application For Performance Testing

The sample application was created  using the Struts2 Maven blank archetype. This application contained a simple stub class to simulate data fetch and a simple JSP file with Struts2 custom tags to display the data.

  • Click here to download the Struts2 Maven sample application with default interceptor stack
  • Click here to download the Struts2 Maven sample application without interceptors (used in test 3)

Tools Used for Struts2  Performance Testing

Following Tools were used for performance testing and capturing various performance metrics,

  • Windows 7 64 bit with JDK 1.6 64 bit
  • NetBeans IDE 7.0.1
  • NetBeans Profiler
  • Apache JMeter 2.5.1
  • Windows 7 Performance Monitor
  • Struts2 Framework 2.2.3.1

Struts2 Performance Testing Setup

My Struts2 performance testing setup consisted of the following rig,

  • Network -  Intel Gigabit controllers on 100Mbps LAN
  • Tomcat Server Machine  – Intel I5 2500K, 16GB RAM, Windows 7 – 64 bit
  • JMeter Test Machine – Intel Quad Core Q9300, 4GB RAM, Windows 7 – 32 bit

Struts2 Performance Testing Results (Phase I)

Test 1 – 500 concurrent users – A load of 500 concurrent users with 100 iterations was applied using JMeter. The ramp up period was 1 second (delay between starting each user). The following diagram shows the response times at this load,

Response Time - Struts2 application under 500 concurrent user load

The average response time at a load of 500 concurrent users is around 1 second. The maximum response time observed is 3 seconds. The following diagram shows the performance metrics obtained from the Windows 7 machine running the application,

CPU Utilization - Struts2 application under 500 concurrent user load

The average CPU time is 59%. There is plenty of CPU time available even at 500 concurrent users.

Test 2 – 2000 concurrent users – A load of 2000 concurrent users with 25 iterations was applied using JMeter. The ramp up time was 1 second. The following diagram shows the response times at this load,

Response Time - Struts2 application under 2000 concurrent user load

The average response time for 2000 concurrent users is under 2 seconds. However some of the requests took about 9 seconds to complete. There are no errors even at this high load. The network utilization of the 100Mbps network is shown below,

Network Utilization - Struts2 application under 2000 concurrent user load

The following diagram shows the performance metrics obtained from the Windows 7 machine running the tomcat server,

CPU utilization - Struts 2 application under 2000 concurrent users

The average CPU time is over 92%. This means that above this load, there will be substantial reduction in performance. To handle more load there are two options,

  • Upgrade the machine (better CPU, multiple CPUs etc.)
  • Run multiple Tomcat instances with a load balancer in front

Struts2 Profiling Results (Phase II)

I used NetBeans profiler to check the hotspots in Struts2 framework code. The profiler was setup to profile only application code and Struts2 framework code.

A load of 250 concurrent users with 10 iterations was applied with a ramp up time of 1 second. The response times recorded was much higher due to netbeans profiler overhead.  The following diagram from NetBeans profiler shows the most costly methods in terms of CPU time.

Method profile of Struts 2 application under load

Let us analyze some of the methods in the above list and see whether any optimizations are possible.

The first method is the iterator in the JSP for displaying the table. Note that this is the time taken for the iterator alone and doesn’t include the time taken for individual property tags.

The prepare() method in Dispatcher is the second costly method. This method manages the locale and encoding of request/response. Optimization is probably possible in this method.

The isActive() method on UtilTimerStack check whether Xwork profiling is turned on.  The back trace for this method shows useful information,

Back trace indicating usage of interceptors

This shows that we have a lot interceptors being called in our application. This are interceptors are part of the default interceptor stack inherited via "struts-default" package. We basically need to create a custom interceptor stack for our application which removes all the unused interceptors.

The doExecute() timing seems to be time taken for writing the response to the client. Most of the time in this is taken by Tomcat classes.

The ONGL seems to be another time hog. Methods such as get(), getValue() and convertValue() which operates on the custom tags is costly.

Finally AnnotationValidationInterceptor is causing the invocation of another costly method isAnnotatedBy().

From the analysis it appears unused interceptors and OGNL are the main areas which can cause performance problems in a simple Struts 2 application under high load.

Conclusion

There are no major performance issues or bottlenecks in Struts2 . A properly designed Struts2 application can handle thousands of concurrent users on a single Tomcat instance. To optimize Struts2 performance, I recommend using a custom interceptor stack with a selected set of interceptors that your application needs.

Click here to get latest site updates delivered to your email. You also need to click on the link sent to your email from feedburner to confirm your subscription.


December 1, 2011 | Posted in Tips No Comments »

Leave a Comment