Performance tuning

The following are some tips and tricks to squeeze the most performance out of Struts 2.

Important OGNL update

For Struts 2 versions before 2.3: the OGNL version 3.0.3 library is a drop-in replacement for older OGNL jars, and provides much better performance. See the following Jira issue for more information: https://issues.apache.org/jira/browse/WW-3580

Turn off logging and devMode.

devMode allows reloading of configuration and validation related files, but because they happen on each request, this setting will totally kill your performance.
When using logging, make sure to turn off logging (esp. Freemarker generates a LOT of logging), and check if a level is enabled before printing it, or you will get the cost of the String parsing/concatination anyways.

Use the Java Templates

If you use the simple theme, and do not overwrite any of the FreeMarker templates, consider using the java templates, which provide a drop in replacement for most tags, and are a lot faster than the regular tags.

Do not use interceptors you do not need.

If you do not require a full stack of interceptors for an Action, then try using a different one (basicStack), or remove interceptors you do not need. Remove the I18nInterceptor interceptor if you don't need it, as it can cause a session to be created.

Use the correct HTTP headers (Cache-Control & Expires).

When returning HTML views, make sure to add the correct headers so browsers know how to cache them.

Copy the static content from the Struts 2 jar when using the Ajax theme (Dojo) or the Calendar tag.

Struts 2 uses some external javascript libraries and cascading stylesheets for certain themes and tags. These by default are located inside the Struts 2 jar, and a special filter returns them when requesting a special path (/struts). Although Struts 2 can handle these requests, an application/servlet container is not optimized for these kind of requests. Consider moving these .js and .css files to a seperated server (Lighttpd, Apache HTTPD, ..).

Create a freemarker.properties file in your WEB-INF/classes directory.

Create the freemarker.properties file and add the following setting (or whatever value you deem fitting):

template_update_delay=60000

This value determines how often Freemarker checks if it needs to reloads the templates from disk. The default value is 500 ms. Since there is no reason to check if a template needs reloading, it is best to set this to a very large value. Note that this value is in seconds and freemarker will convert this value to milliseconds.

You can also use struts.freemarker.templatesCache.updateDelay constant to achieve the same effect.

See also: Freemarker configuration properties

Enable Freemarker template caching

As of Struts 2.0.10, setting the property struts.freemarker.templatesCache to true will enable the Struts internal caching of Freemarker templates. This property is set to false by default.

In Struts versions prior to 2.0.10, you had to copy the /template directory from the Struts 2 jar in your WEB_APP root to utilize Freemarker's built in chaching mechanism in order to achieve similar results.

The built in Freemarker caching mechanism fails to properly cache templates when they are retrieved from the classpath. Copying them to the WEB_APP root allows Freemarker to cache them correctly. Freemarker looks at the last modified time of the template to determine if it needs to reload the templates. Resources retrieved from the classpath have no last modified time, so Freemarker will reload them on every request.

When overriding a theme, copy all necessary templates to the theme directory.

There's a performance cost when a template cannot be found in the current directory. The reason for this is that Struts 2 must check for a template in the current theme first before falling back to the parent theme. In the future, this penalty could be eliminated by implementing a missing template cache in Struts 2.

Do not create sessions unless you need them.

Struts 2 does not create sessions unless asked to (for example, by having the createSession interceptor in your interceptor stack). Note that when you use SiteMesh however, a session will always be created (See http://forums.opensymphony.com/thread.jspa?messageID=5688 for details). The I18nInterceptor interceptor can create sessions, so make sure you remove it, if you don't need it.

When using Freemarker, try to use the Freemarker equivalent rather than using the JSP tags.

Freemarker has support for iterating lists, displaying properties, including other templates, macro's, and so on. There is a small performance cost when using the S2 tags instead of the Freemarker equivalent (eg. <s:property value="foo"/> should be replaced by ${foo}).

Next: Interceptors

  • No labels

1 Comment

  1. ---------- Forwarded message ----------
    From: Vlad <forum-struts-dev@opensymphony.com>
    Date: Mar 24, 2007 2:59 AM
    Subject: Re: OGNL performance detrimental to Struts 2
    To: dev@struts.apache.org

    When I see OGNL classes in exceptions stack trace, I believe it is not as fast as 2+2.
    But I have never thought to replace <ww:property> tags with <%= %> scriplets. <ww:property> performance is enough for me, for now.

    WebWork form tags could be really slow. After I have moved templates out of webwork.jar to WEB-INF/template directory, performance improved drastically. Before that my application spent about 90% of CPU time in Freemarker.loadTemplate method.

    I believe that the test which caused this thread was using form tags. What could be done more to improve performance of form tags?

    Several months ago I did the following evaluation for my project.
    Since I was not going to put too much form tags on one page, I had no concerns about its performance impact. But I had a lot of design elements which were used over all pages and could appear many time on one page. I had thought about solution how to make such design elements reusable:

    1. JSP include via include directive
    2. JSP include vie jsp:include JSP tag
    3. using WebWork component tag with own template
    4. own WebWork tag with JSP template
    5. own WebWork tag with Freemarker template
    6. own WebWork tag with Velocity template
    7. JSP tag without template (HTML printed directly from Java code out)

    Test page was create to test performance of these different approaches. The page printed the same component 50 times and printed the time required to render the components (50 components). The component itself represented link to user profile:

    It was tested on Tomcat 5.5, Windows XP professional, WebWork 2.2.4

    Test results:

    Test Time (ms) to render 50 components
    1. include directive 47
    2. jsp:include 94
    3. ww:component tag with jsp template 109
    4. b:jspSimpleProfile tag 79
    5. b:ftlSimpleProfile tag 46
    6. b:vmSimpleProfile tag 32
    7. b:lightProfile tag 0

    My conclusions were:

    • JSP include directive suites for the cases when the included page doesn't contain much logic and is not used often on a page.
    • jsp:include - better not to use it. Instead of it use include directive - it is faster. If you need to pass additional parameters to the included page, you can put them into value stack.
    • avoid using ww:component tag. Use JSP include directive instead - it is faster.
    • if you have much or complex logic and you need complex rendering, create your own UI tag with separated template file - the same way WebWorks does it. Extend your Tag and Component classes from WebWork classes. Use Freemarker template, since it is faster than JSP. Velocity teplates are even faster, but it is better to use Freemarker templates since all WebWork components using it and you can get working examples or event reusable template parts.
    • if you have simple view but with complex logic or if it used very often - write your own JSP tag with template hardcoded in Java code.

    Thus I think replacing WebWork/Struts2 form tags by simple JSP tags with HTML hardcoded in Java code will boost performance for tests where form tags are used extensively. But if you would like to have form tags as flexible as they are now, the current implementation is optimal. Their performance is comparable with JSP include directive. I hope that form tags with externalized templates will stay in Struts 2.x (smile). You could have two kind of form tags: simple one with hardcoded in Java template and one with Freemarker template.

    To avoid such long threads in future, probably it makes sense to add some performance benchmark page in struts examples distribution.