Recently I was helping with performance of one of our jboss seam applications, apart from the usual db interactions, interaction between our ui and seam components were making a huge impact on performance. In short, if you have a seam application that avoids using @BypassInterceptors and has Component methods called from EL in the UI, this blog may be worth a read. Links to some of the available tools and the home grown ones are provided at the end of the blog.

Taking a step back lets think about a select with 12 select items like the creditCardExpiryMonth in book.xhtml of jpa example, this typically will look something like

<h:selectOneMenu id="creditCardExpiryMonth" value="#{booking.creditCardExpiryMonth}">
<f:selectItem itemLabel="Jan" itemValue="1"/>
<f:selectItem itemLabel="Dec" itemValue="12"/>

Lets try to guess how many times the value EL (booking.creditCardExpiryMonth) may be evaluated on the sun jsf ri version 1.2_04, the correct answer is 12(once for every select item to determine whether or not to mark the select item as selected), think of the havoc it can cause if this getCreditCardExpiryMonth method were to be invoked on a seam component (with all its interceptor chain). This seems like a straight forward case and you may be sure that in your application you do not have any such case, but wouldn’t it be great if we could check if this really is the case, for such checks we can use AOP Based EL call measurement tool or Component Instrumentation for invocation count and time, personally I prefer a modified version which combines the two.

Great, so we now know that we have problems with EL evaluations, what do we do about it. First stop, try to outject it, DataModel annotation is a trusted friend there. Another way of getting around such issues is to cache the actual EL value so that subsequent invocations can be supplied from the cache rather than needing a proper evaluation. Adam Warski in his blog documents and provides source for such a component, with a few enhancements this component can solve most of such re-evaluation problems (I call this enhanced component CachingSet). In the case of selects, however, I prefer my own renderer which caches the selected value for the timespan of rendering this select (MenuRenderer).

Rather than guessing blindly which components in the UI are taking more time, it would be great if we had some way of printing the time taken for any component, enter timediff. A small component which measures the time taken for its child to be rendered, for example in case if I wanted to see how much time the above select takes, I could do something like

<app:timediff childName="creditCardExpiryMonthSelect">
<h:selectOneMenu id="creditCardExpiryMonth" value="#{booking.creditCardExpiryMonth}">

This would print on the screen the actual time taken for creditCardExpiryMonth select to be rendered. Depending on the time taken we could then think of renderers or any other such changes.

You may be surprised but at times selects depending on their size can take a huge chunk of time, part of it is because of the way the i18n labels are looked up from the properties files, part of it is the way the component tree becomes more complicated. I have found that for static selects, I can reduce this rendering time considerably if the actual html snippet were to be cached and then a small javascript snippet were to select the actual value. This helps in reducing the rendering time of selects with a large number of items drastically (CachingEnumSelectOne), especially if the select items are coming from an enum. For general caching seam cache tag is handy, unfortunately as selects are not actually static, so need some javascript magic and can not be handled with seam cache tag.

We also have some screens where the viewid is dynamic (linked to an EL expression), as seam allows page level message overrides, this meant that the viewid EL was getting evaluated for each label resolution on this page. Since we do not allow page level overrides, we extended the messages component to not do page level override lookups, this helped a lot in performance (assuming that the new version of seam has a better implementation of this part, you may still want to see if this is the bottleneck in your application).

It is always a good idea to expose hibernate stats and cache stats over JMX, using seam this is pretty easy and a simple component (class called HibernateStatistics) helps us do this. If we are using ehcache the cache management mbeans can also be exposed, this is less than 20 lines. The output can be seen in the jmx-console of the appserver.

Code links
Code base for HibernateStatistics, CachingSet, MenuRenderer and CachingEnumSelectOne

Sources as jar file

Original caching Set and its details at Adam Warski’s blog

AOP Based EL call measurement tool

Component Instrumentation for invocation count and time