Finding the getters slowing my JSF page

Introduction

Ever find that some of your JSF pages have suddenly slowed down? Like browsing through sludge? A getter that’s doing somewhat more than it should be is a fairly likely cause, especially given JSF’s tendency to call getters more than once during a standard life-cycle.

As projects with larger teams grow, inevitably some code manages to hide away in dark crevices away from the light of code reviews for some time. Profiling tools exist to help us find these (hey dynaTrace! *waves*), but what if you don’t have access to one of these nifty tools? Specifically the tricky ones, like the reflective EL magic?

Reflection magic is fairly hard to pull out in a generic manner – so let’s let common sense prevail and pull out the information we need directly. JSF lets us write our own custom EL resolvers – this seems like a mighty task but instead of writing an entire resolver we can just piggy-back off an existing resolver whilst grabbing some time data before and after.

If the time took longer than a set amount, we can notify the developer through the logs and they can go and have a look at the over-ambitious getter. Not too hard – let’s take a look.

BeanELResolver

The resolver charged with the task of resolving properties off of beans is the javax.el.BeanELResolver. This is the one that we want to measure, so we can extend from it. The bean EL resolver is all the way near the bottom of the EL resolver order (see pg 189 of the JSF 2.0 spec), so there’s a lot of stuff it won’t be able to resolve. Rather than trying to work that out, we just try to resolve it with the bean resolver and hand it on to the next resolver if that doesn’t work out.

Let’s have a look at that, before we worry about any timing code.

We attempt to get the parent BeanELResolver  to resolve the value for us. If the bean resolver fails, we make sure that property has not been set to resolved, then we return null  so that the next resolver in the list can pick it up.

To register the new EL resolver, add this to your faces-config.xml

Easy enough – what about the timing?

Timing

There are two different sets of timing that we are concerned about – user timing and CPU timing. User timing (or wall clock timing) is the amount of actual time that passed while the code was executing.

This includes time spent suspended, while other threads were running, swapping threads etc. CPU timing on the other hand is just the amount of time that the CPU spent on our code in particular.

We’re going to look at these two times – so that we don’t spam the developer with every getter called, we’ll require that the time took longer than 10ms (we’ll make this dynamic before we’re done here).

Both of these times are made available to us in recent Java versions (and JVMs) as part of the java.lang.management package. We’ll make sure that they are available on our JVM before using them though – in the case of the user time we can fall back to system time. In the case of CPU time, we’re out of luck. It’s likely that the JVM being used will support these features though.

In the case of CPU time we return a 0 if it is not supported, and in the case of the user time we return the current nanoTime  from the system.

To get the elapsed time, we grab the before and after times, subtract them and convert the resulting nanoseconds to ms for easier comparison to our cut-off time. There’s a handy class called  TimeUnit that handles this for us.

This makes the full getValue  method look as follows.

There are a couple of constants here for messages – these are shown in the full code listing at the end. One other bit of convenience remains – instead of making the developer climb into the source to change the cut off time, let’s rather let them set it in their  web.xml  and retrieve this when the resolver is constructed.

Setting the value is easy – just modify the web.xml to look something like this.

 

Getting the value is almost as easy – the EL resolver is constructed when the system starts up, so in the constructor we need to extract the value from the web.xml. We can get this via the init context on the faces context – then we parse it and fall back to a default value if it doesn’t exist or is unparseable.

Full Code Listing

Here’s the full code – hopefully it’ll help you speed up your page loads. Remember to hold your breath until the page is fully loaded to help with the sense of urgency.

 

Tagged with: , , ,
Posted in Front-end, Java

Leave a Reply