Industrie IT

We mean business

Company news
Follow us @industrieit

Stateless JSF – high performance, zero per request memory overhead

UPDATE (10DEC11) – BETA 4 RELEASED… click here

UPDATE (07DEC11) – BETA 3 RELEASED : sub-millisecond non-render GET overhead, JSTL support, adaptive pools… click here

UPDATE – BETA 2 RELEASED… click here

The tables below provide summary results for the stateless JSF implementation discussed below.

Requests per second

STATEFUL JSF STATELESS JSF SPEEDUP
Hello World 2050 req / sec 2158 req / sec +5%
Small view 1000 req / sec 1850 req / sec +85%
Large view 20 req / sec 750 req / sec +3750%


Overhead – framework time outside Component.render();

STATEFUL JSF STATELESS JSF SPEEDUP
Small view <1 millisecond
Large view <1 millisecond >3,000%

 

NOTE: Since writing the article we have noticed our load test times were being adversely affected by the realtime graph listener in JMeter. Actual performance is significantly better than stated in the article. The small view sample page for example renders stateless not at 26,500 rpm but 110,000 requests per minute (large view 45,000 rpm). Stateful JSF also does better on the small views, though no better on the large

Browser side latency improvement – large view

Introduction

Now that no one company dominates the browser space, some pretty impressive browser implementations (both in render speed and javascript performance) are available, and standardisation is becoming quite complete. These facts will result in a movement of normal website development further to the client side. It’s already happening at a rapid rate.

Yes, component oriented development will be the major pattern for web development. But the ‘components’ are going to be objects sitting on the client browser, written in JavaScript. The sweet spot for full blown JSF has therefore, IMHO, passed. The idea of requiring server interaction for most DOM changes is already starting to seem like it came from another age. Will there actually be any server-centric web framework in common use for new business web apps in the not too distant future?

However, corporate environments always have a legacy base of software preventing rapid change. Many of you have an existing investment in JSF or desire to remain with the JEE standard. We need to provide a mechanism where JSF can be used as a lightweight compositing mechanism, with very low CPU and memory overhead if desired, in order to transition to a more client side approach to web development.

It is reasonable to expect the performance of page rendering to be mostly dependent on the amount of mark-up rendered (aside from time spent outside the framework like in database calls). Currently this is not the case with JSF. Page performance is largely related to the size of the view tree, regardless of whether the vast bulk of it is excluded from render due to being in non rendered branches.

This fact is the reason why many JSF apps seem so sluggish – even when they are rendering what appear to be simple pages.

JSF users, at this point, will start paring back page complexity by putting sections in multiple pages where not really warranted, seeking to minimise the view size. You could also do things like use JSTL c:if tags to trim whole branches from the view. However, you can get side effects. For example, using c:if to initially exclude a composite component from a page prevents any associated resource references from being included in the html head. This then causes issues on subsequent partial ajax rendering if and when the component is displayed. That’s why JSTL is generally discouraged from facelet based templates. If you do not use it, however, the view grows quickly.

The whole point of component based development though is to be able to handle more complex pages. In this sense, JSF as-is has fallen short of its goals. You don’t have to push the limits much to get less than stellar performance.

So what can we do to make JSF zippier?

The fundamental question is:

DO WE REALLY NEED A FULLY MUTABLE VIEW?

If not we can gain considerable performance advantages. In my experience it’s not commonly used, or is better done in the client, and for these reasons the costs of fully supporting it as things stand are too great.

Introducing Stateless JSF

Those familiar with the way the Tapestry framework operates will have an idea of where we are going with this.

Processing the mutable view structure in JSF (whether originally INTENDED or not) is IN PRACTICE a heavyweight operation for non trivial views. There seems to be an ongoing debate regarding this. Having used JSF for many projects, this has, for me, been settled.

With this in mind – rather than constantly recreating the views, we are going to pool and re-use them for other requests.

For this you will pay the price of:

  •  * You can’t (or shouldn’t) create the view dependant on any data that changes with respect to each request (normally easy if you don’t use JSTL).
  •  * You can’t (or shouldn’t) mutate the view after it’s created.
  • * All persistent component state should be flushed to backing beans (you are most probably doing this anyway).

I say “you shouldn’t”  because in the current implementation the altered  view is put back in the pool as-is. If you do not respect the restriction, the pooled views will diverge in structure and you will start to get differing behaviour for each request. We could enforce this with a hash check and flag an error if a mutated view is returned to the cache, but this will suffice initially.

On the upside – views though static can be as complex as you want with very little performance penalty. Rather than changing the view in time, ramp up complexity by putting in many branches that are conditionally rendered.

An Overview of the Implementation

One plus in our solution is that we ARE NOT changing any core implementation classes. We are simply making use of the ‘plugability’ and extensibility of JSF (something they did get right), by slightly (or majorly!) overriding the state manager, the view handler, and the view language factory. These can all be cleanly overridden by adding entries to the faces-config.xml file to provide alternate implementations.

We will not, therefore, need to provide custom implementation jars at all. We will be using the default JSF 2.1.3 Mojarra release jars. Note that although we provide alternate implementations of these components, we are overriding the existing implementation classes, so it’s not guaranteed you can move the classes to a different version of Mojarra, and certainly not MyFaces. Porting should not be difficult however.

I have also taken care to allow an incremental changeover. Individual pages can be marked as running in stateless mode. The remainder will operate exactly as they do now.

Here are the changes that are required to be made to run stateless:

  1. * in the view definition language factory, we will return a subclass of the FaceletViewHandlingStrategy  that only runs buildView() ONCE. We do this by placing a marker on the ViewRoot to indicate we’ve already built the view.
  2. * override the state manager to NOT store any per view state (huh? We’ll get to that)
  3. * override the view manager to pool and re-use UIViewRoot components.
  4. * provide a phase listener to return the view to the pool after render. Note that the pool manager will enforce a minimal time in the pool before supplying to a new request. This is because the post render event is not the end of JSF processing and we must ensure there is no overlap between requests.

When we do this, we are forced to accept some restrictions compared to stateful JSF.

  •  * make sure the view is created without regard to any data that varies between requests. This is normally easy to do if you steer clear of using jstl tags.
  • * be careful with JSTL tags (particularly c:if). Views are only built once, so if a c:if test initially returns false, it will never appear in any view. This is unlike normal behaviour where buildView continuously tests the conditional and inserts/trims the view as needed. c:if tags can be used to prune the UIViewRoot tree at build time  to reduce the latency of buildView and minimise the viewstate. However, now that we are caching the view, page performance is not affected by buildView. Make the pages as complex as required for the function and exclude as needed with simple conditionally rendered fragments. Do not prematurely optimise – you will be surprised how much you can pack into the view compared to stateful mode.
  • * The addToView event can’t be relied upon – its only called once on initial creation and not every time we are re-using the view
  • * It is normally possible (though not common) to work with JSF directly against the UIComponent objects in the view heirarchy, and have the state retained across requests without binding to a backing bean. Since we are not retaining any per view state this is no longer possible.
  • * Some other features I don’t use and haven’t tested for may not work (let us know).

Before being returned back into the available pool, the component tree is traversed, resetting all UIInput components. This is obviously to ensure that a field submitted from user 1 is not displayed to a different user 2 when the view is later retrieved from the view cache and re-used. A non-initialised UIInput sets itself from the backing bean – which is exactly the behaviour we need. However, state that is not flushed through to backing beans or returned to the server for later submission due to validation failure is lost. You can think of this as ultra-thin split client/server side state saving (client side on validation failure, server side on success)

A word of caution. DO NOT just plug these classes into your app without having a good understanding of the JSF lifecycle, the persistent state of your custom components, and your particular circumstances. To overcome deficiencies in previous versions of JSF, or to achieve some particular behaviour, components have been developed that either mutate the component tree and/or store some sort of hidden state in the tree. Now I don’t use any of them, but if you do, the data will be retained in the view pool, possibly to be later used in the request cycle of a different user, and in the worst case this will be used to render markup and COMPROMISE CONFIDENTIAL USER data to others.

The only data expected to be flushed as temporary state through the view during a cycle (that needs to be cleaned up) is assumed to be components derived from UIInput. This includes the form fields. Any custom component you are using (and possibly some from the common JSF component libraries) that stores state into the view may be problematic in this regard. CHECK!!!

JSF State

The concept of what exactly is ‘STATE’ in JSF is also confusing. In a fully mutable view we must record the structure of the tree, as well as any persistent state related to each of the components in the tree.

If the tree structure does not change, the tree structure is by and large stateless. If you mandate all form data must be bound to backing beans, you don’t need to store the fields of this stateless tree either.

Indeed, the frustrating thing about all this JSF state saving is that if you don’t manipulate the tree structure (more common than not in my experience), all your views are exactly the same, and the UIComponent values may actually all be replicated in your backing beans.

Things like el expressions are just late bound string literals evaluated at a later time, but their representation in the tree is a simple string. The dynamic behaviour in this regard is conferred by having different backing beans presented to the view at different times (controlled via scope).

Now, data submitted from form values is, during the JSF lifecycle, stored in the view and processed. The UIViewRoot is not threadsafe, and that is why we must pool them and ensure they are not used in two different cycles at the same time.

However the state in the viewroot only exists during the actual request cycle. Any form data is bound into the tree at phase 2 of the JSF cycle. If it fails validation, it’s sent back to the client browser to be rendered as form fields again (our client side state). If it validates it is flushed through to a backing bean which, if appropriately scoped is retained across requests (our server side state, if you will).

So if any input values in the tree have already been replicated somewhere else and the tree doesn’t change. Is it REALLY necessary to persist ANY per view state? From what i can see, no (correct me if i am mistaken)

The advantage of this pooled view approach is that the actual views are cached, you only need as many to handle the maximum CONCURRENT requests, and they belong to the entire application. State flows through these pooled views temporarily during the JSF lifecycle, and end up either being sent back to the client or flushed through to your backing beans.

At this point the view can be reset and sent back to the free pool to be reused.

In the event that all of your backing beans for a view remain request or application scoped, you can run a JSF site for which there is no incremental persistent per request or per user retained state on the server, AND you forego continuous per-request CPU hit of the buildView part of the render phase, which can be significant (we’ll see how much shortly).

You will in this case, in the steady state, achieve scaling along the lines of what you’d expect from a simple front controller based framework like struts. This is definitely NOT the case with JSF out of the box, and severely limits its use.

With that said, let’s have a look at performance gains using our stateless changes.

I’m going to make a simple page and ramp up its complexity using the jstl c:forEach tag. As previously mentioned JSTL tags are applied at build time to affect behaviour during construction of the view tree. Foreach will actually create multiple UIComponent siblings and place them as children within the parent component. This is in contrast to the facelet ui:repeat which creates one component (uirepeat, funnily enough), and does request time iteration (and ‘smart’ fast forwarding on postback) to render the same component with different attributes.

One bug I have found is that calling buildView on a viewRoot is not idempotent. I find that the composite components don’t hold their place in the child list. They get moved to the end and therefore render in the wrong place on the page. If you hack around with the code and find this happening, you are calling buildView on a pooled viewroot. If you create a view and build it fine. If you build it any more than once, the composite components get re-arranged.

Performance Results

Testing was done on a Core2 laptop, Windows NT, Apache Tomcat 7.10, JDK 7u1, default settings. Incidentally – the escape analysis based optimisations  in Java 7 (lock elision and scalar replacement) can confer very impressive performance gains.

I’m going to break the testing into two separate tests to illustrate the two advantages gained by our stateless model – CPU (single user)  and memory (multi-user).

In the first case I will saturate the server from JMeter, retaining the session cookie, to gauge straight out speed without worrying about memory overload (only one user session will be created).

Single User

A simple page with a facelet included, a composite component, and a small number of inputs. In other words, a trivial site not comparable to any real site. A page such as you would find in a JSF tutorial.

STANDARD JSF 2.1.3, SIMPLE PAGE, 1 USER:

Ok so trivial page, single user, we get around 11,000 pages per minute after giving hotspot a chance to do its thing (18 milliseconds per request).

Now let’s try our stateless model under the same conditions:

STATELESS JSF 2.1.3, SIMPLE PAGE, 1 USER:

Ok stateless we top out at around 26,500 requests per minute (A 135 percent increase over standard.

Now if you left it at that you’d think it’s an improvement but not a major issue –even 11,000 requests per minute is more than enough to satisfy most throughput requirements.

You would, however, be grossly MISTAKEN.

Intuitively you would feel page time is mostly related to the complexity of the rendered output. This does not appear to be correct – in current implementations of Mojarra its more related to the complexity of the view, regardless of whether it’s all rendered or not. This is the thing that trips up those new to JSF.

To highlight my point, let’s increase the complexity and size of the view, while at the same time rendering exactly the SAME MARKUP. We do this via a jstl c:forEach iterator inside a non rendered fragment. C:forEach is a build time tag that will cause real individual UIComponent siblings to be created and placed into the view. In this example we are inserting 1000 panelGroups into a hidden fragment.

STANDARD JSF 2.1.3, COMPLEX PAGE, 1 USER:

WHOA!!! What’s happening here??? We are rendering EXACTLY the same markup, but the site has slowed to a crawl (an increase in render time of 1200%) to a quarter of a second.

What is happening is the buildView portion of the cycle is FAR eclipsing the actual rendering .

Buildview seems to be an integral part of the render cycle, regardless of request type (GET, postback etc).

Let’s try the same page with our stateless changes:

STATELESS JSF 2.1.3, COMPLEX PAGE, 1 USER:

You read that right – on the more complex view (though rendering the same output) we’re still levelling off at 16,500 requests per minute (median 10 milliseconds, 20 times more throughput than the default stateful mode).

NOW – tell me – which of the two scenarios do the pages from your complex website more closely resemble (simple or complex view)? It’s not difficult to assemble even more complex aggregate views, and watch as one page request monopolises a good fraction of a second of a fast CPU’s horsepower.

Multi-user

Finally – I’m going to try the absolute worst case scenario for standard JSF – a server saturated from unrelated requests, against a complex page. I’ll mimic this from JMeter by adding a cookie manager to the request element and marking the ‘clear cookies every iteration’ checkbox, so a new session gets created on each request.

STANDARD JSF 2.1.3, COMPLEX PAGE, MULI-USER:

With the default JVM heap settings for JDK 7, and a default tomcat 7.10 installation, after a mere 1200 independent web requests, the server has essentially locked up, after disappointing initial performance to begin with. The server’s memory has been exhausted purely due to persistence of the (IDENTICAL!!!) views, and it’s spending most of its time in garbage collection. Pages start taking seconds to render.

Now the above scenario is the most likely for a standard public website. If you have a session time of 30 minutes, with a complex view, server side state saving, and unique visitors, on default JVM heap settings, as little as one request per second will cause enough state to be stored to bring your machine down. The longer the session idle time the worse it gets.

You can see why people are having problems with JSF, and I don’t necessarily blame them. Its totally foreign behavior compared to what they are used to. Now I am using server side state with partial state saving turned off (pre JSF 2 you don’t have the option anyway). Partial state saving will give you SOME headroom (albeit from a low base). You could also use client side state saving, however on complex views (even with partial turned on) this gets VERY big and introduces additional CPU inefficiencies as well as unnecessary payload on each request. We have already shown CPU usage is excessive to begin with due to restore/buildView. Switching to client side state will make that worse. Security restrictions may also prevent this option.

This is the fundamental issue with JSF as it currently stands – on large views (the views you’d expect to be working with to take advantage of component oriented design) JSF is so demanding in both CPU horsepower AND memory as to be unsuitable for a whole range of situations (in my opinion).

I find for non trivial sites we have to compensate by having lots of (very fast!!! processors), smart session management (fast cleanup rather than long idle timeout) and multi-gigabyte heaps. And even then you could still possibly get into trouble on a public facing website rather than an intranet site, where there is less control over expected unique user base.

You will see from the facelet template representing my sample page that I am using JSTL to create 1000 panelGroups in a non rendered fragment. This may seem excessive, but  from my experience, it is by no means difficult to create a complex view with a component count of that order.

As a final test, let’s try our stateless model on the same page, hit with unrelated requests:

STATESTLESS JSF 2.1.3, COMPLEX VIEW, MULI-USER

Not bad! We’re still up at almost 16,200 requests per minute, continuous (essentially the same as single-user since we are not saving any per view state).

I have run this test for millions of cycles over several hours at 100% cpu to ensure that no session data is created by default and there are no discernable memory leaks. Garbage collection performance is also good. In the above test only a handful of full collections were performed over hours at full throttle, showing that whatever objects created by the framework to service a cycle are short lived and cleaned during an incremental only. If you switch to standard JSF with server side state saving, the persisted views rapidly end up in the old generation and influence pause times on the full sweeps.

Clearly, our stateless model degrades at a far more comfortable rate than standard JSF, as would be expected.

Incidentally, if we put everything inside the h:form in a non rendered fragment (essentially rendering an empty page aside from html boilerplate), it tops out at 35,000 rpm. That’s around 5 milliseconds latency.

You can view this 5 milliseconds latency as the ‘steady state framework overhead’ of Stateless JSF (on my core2 laptop at any rate). Since we are pooling views, this should not change that much. 5 milliseconds I can live with.

Postbacks will incur additional overhead due to the extra phases and will depend on how much of the view you push through to JSF (using <f:ajaxexecute=”….”/>  for example. Stick to good use of @this where appropriate. Provided you are rendering from simple beans in memory, GETS shouldn’t change much.

If the backing beans associated with a page view do not store any persistent session or application state (as is the case in our example) – you get that throughput FOREVER regardless of how many unique users, individual get requests, or postbacks are submitted. The framework no longer retains any per view, per request or per session state as part of default operation. Of course you could introduce session state by appropriately scoping your backing beans (like any other framework), but this is controlled by you, outside the scope of JSF, and is far more familiar and predictable.

And as a final plus – say goodbye to stale views. Postbacks always work since the views never change and you can always post into an available pooled view. Of course, you can still time out your session, but that’s not a JSF issue and doesn’t apply if your backing beans aren’t session scoped.

So there you have it. With these simple optimisations to the default internal JSF implementation modules you are free to use JSF in a lightweight, stateless fashion if desired, with vastly increased cpu and memory performance, while keeping the vast bulk of the normal jsf behaviour intact. Yes views are immutable, but you may have never made use of runtime view mutation anyway. Yes, you have to bind to backing beans, but you do that anyway.

Besides, components will increasingly be client side, and you can use a good javascript framework like JQuery to change the client DOM however you like, bypassing many JSF cycles through the use of JSON (I find this is how i use it now). The goal of Stateless JSF is to allow the framework to become a less instrusive compositing layer, with much of the  magic done client side if desired.

This should open up JSF to many more uses, and allow a transition across to client side programming with minimal overhead.

It’s important to note – it’s not all or nothing. Stateless JSF has been designed so stateless and stateful pages can co-exist as required. You don’t have to switch everything over. If there is only one page, or a public section of your site that is causing issues, you can run that stateless and run the rest stateful as is. The stateless implementation classes override the default implementation classes and simply fall back to default operation for pages not explicitly marked as stateless.

The Code

PLEASE REGARD THIS AS BETA QUALITY SOFTWARE. THE RE-USE OF VIEWS REQUIRES THOROUGH REVIEW TO ENSURE WE ARE NOT ACCIDENTALLY LEAKING DATA ACCROSS REQUESTS.

Download files and mercurial repo are available from bitbucket:

https://bitbucket.org/industrieit/stateless-jsf

Note that it is tested with MOJARRA 2.1.3. Since we are extending some implementation classes it may NOT work for other versions. In this case it’s best to just include the small number of source files in your own project and tweak as required.

If you  are not interested in how the code works and are happy with Mojarra 2.1.3, you only need the binary jar. The zip file conatins a full packaged maven project (with seam and spring) with prebuilt war in the target directory that can be deployed (Tomcat 7.10  tested) directly. You could also use the existing maven project as a base for your own development.

If you would like to tweak the code, you may copy the source files from package com.industrieit.jsf.stateless.impl.* and include them in your own JSF 2 project.

To enable Stateless JSF, include the abovementioned package in either source or jar form, and add the following settings to your faces-config.xml (custom settings such as those for seam, can be retained). We need to specify the state manager, the view manager, the view declaration language factory, and add a phase listener.

<?xml version="1.0" encoding="utf-8"?>
<faces-config version="2.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd">

  <name>StatelessJSF</name>
  <application>
    <state-manager>
    com.industrieit.jsf.stateless.impl.SJSFStateManager</state-manager>
    <view-handler>
    com.industrieit.jsf.stateless.impl.SJSFViewHandler</view-handler>
  </application>
  <factory>
    <view-declaration-language-factory>
    com.industrieit.jsf.stateless.impl.SJSFVDLFactory</view-declaration-language-factory>
  </factory>
  <lifecycle>
    <phase-listener>
    com.industrieit.jsf.stateless.impl.SJSFPhaseListener</phase-listener>
  </lifecycle>
</faces-config>

 

Stateless JSF is made to work seamlessly with standard JSF. By default, nothing will change. In order to flag a page as stateless, you must place an appropriate child component of the view root as such (note the panelGroup above h:head):

<!DOCTYPE
composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:rich="http://richfaces.org/rich"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:a="http://richfaces.org/a4j"
xmlns:b="http://java.sun.com/jsf/composite/comp">
  <h:panelGroup id="SJSF" rendered="false" stateless="true" />
  <h:head></h:head>
</html>

 

Normally components at the same level as the h:head tag are the direct children of UIViewRoot. The marker component must have an id of SJSF and it must have an attribute called stateless valued true. Unless this component is defined and placed in the correct location, Stateless JSF will operate exactly the same as regular stateful JSF. To test whether the page is operating stateless, view the rendered markup. If stateless, the value of the javax.faces.ViewState hidden field will be “STATELESS_JSF”, otherwise it’s normally a concatenation of two random numbers and indicates normal stateful JSF is in operation for that particular view.

STATELESS:

<input type=”hidden” name=”javax.faces.ViewState” id=”javax.faces.ViewState” value=”STATELESS_JSF” autocomplete=”off” />

STATEFUL:

<input type=”hidden” name=”javax.faces.ViewState” id=”javax.faces.ViewState” value=”-3761328746132864:7561873643853” autocomplete=”off” />

Questions

Does it work with Seam?

 Yes, tested with Seam 2.2.2, (jars are in the zip though config commented out in faces-config.xml), however conversations are not currently working. It would be nice if someone could identify the issue. I would guess conversations are set up by the seam phase listener in some way. Also – DO NOT USE page scope on stateless views.

What about JSF 2 view scoped beans or Seam page scoped components?

Don’t use the Seam page scope! I am not clearing it at the moment. The JSF 2 @ViewScoped beans are stored in the map accessed from UIViewroot.getViewMap(). I am currently just clearing them as I prefer to keep state outside of JSF. Beans stored in the view are problematic. Storing state in the tree prevents you from controlling identity. You can’t reuse the ‘same’ component in a different page, and you lose the state if you refresh the page. There are other options. Some sort of ‘conversation’ managed outside of JSF is more flexible.

I could have persisted the viewMap in the session keyed to a unique viewstate id the same way stateful JSF does, but have chosen not to. This automatically allocates session data per view, exactly what I’m trying to avoid. I’d rather avoid ‘getting a little bit pregnant’. Either run fully stateless or don’t bother. Hence the fixed viewstate id string of “STATELESS_JSF”

How does this work with component libraries?

Not sure – let us know.  Theoretically should be ok, but any components that try to persist to the view and not a backing bean will not work properly. Not only that – if the component does not subclass UIInput the state will not be cleared when put back in the free pool. This could be dangerous as it will inevitably be used to service a request from a different user.

Most of the sites I work on have exacting styling requirements and most of the component libraries are not flexible enough to be styled freeform. Most of the components I do therefore are custom composites mainly utilising the base JSF tags, with advanced behaviour implemented on the client through integration with JQuery and JSON. This makes a lot of the JSF tags and components redundant, and limits JSF interaction to mainly coarse grained submissions only. The new JSF 2 features allow you to create a component comprising backing beans, html markup and javascript to be developed, tested, packaged and versioned independently, and incorporated into the aggregate web application as a jar file. This has merit on its own if we can avoid the overhead of standard JSF.

My Facelets don’t hot deploy when running STATELESS!

Yes, the views are being cached – currently its buildView() that determines whether the facelet files are changing and we no longer call that on each request. Either restart the container, or provide an action that calls SJSFStatePool.clearPool() to clear the viewcache. You could have a simple page that encodes the call in inline el. There may be a better way but that’s whats in the current release.

There is a flaw in the design / I have an idea that can make it better.

Great! Thats why it’s open source.

Cheers…

Rudi

The views expressed on this blog are those of the author and do not necessarily reflect the views of Industrie IT. 
This entry was posted in Technical and tagged , , , , . Bookmark the permalink.

29 Responses to Stateless JSF – high performance, zero per request memory overhead

  1. Jacob Hookom says:

    Very nice, brilliant job!

  2. Lincoln says:

    Have you considered checking last modified timestamps of the Facelet hierarchy? This could be optimized by only performing the test if javax.faces.PROJECT_STAGE == Development. You could also just clear the cache on each request in that case, and when the switch is flipped to Production, you get the caching.

    This is incredible work. What is your plan for support or ownership in the future?

  3. k placko says:

    Your percentage calculation in the Overhead, Large View portion of the introductory table appears to be incorrect.

  4. Nitin says:

    I was thinking of using jsf / primefaces for a community site, thinking about its simplicity. no need to get into JS/JQ
    Looking at the post, I have started looking at it with a pinch of salt in my mouth.
    I think I need to get back to asp or php.
    Please let me know if I would be looking at JSF running a community site that may host XMPP based conversations.

  5. Ray says:

    Awesome !

  6. rsimic says:

    hey we’re finally getting some traction.

    thanks Jacob – i think you were pushing for a stateless mode in the original spec weren’t you?

    —-

    hi Nitin – i am giving worst case scenarios. Your requests won’t all be from unrelated clients. Your views probably won’t be as big. If you use delta state saving you’ll get maybe 4 times more headroom off the bat. Also we used default JVM heap settings. You could also shorten the session timeout (we actually have a smart session cleanup system where a javascript component pings the server with keepalive packets – the session cleans up within minutes if you leave the page but remains active for hours if you don’t). In any event you must bear the default stateful nature of JSF in mind. In very high traffic sites, stateful JSF in not appropriate in my opinion (that’s why we wrote this stateless plugin). I would recommend you bite the bullet and learn how to do it client side (that’s where it’s all going and some JSF components just wrap existing JQuery components). After you become proficient in frameworks like JQuery and understand Javascript as a first level language, its really the easiest way to go. Web framework wise the client’s getting fatter and the server side is getting thinner (and may well disappear in some instances), so server side framework choice is becoming less and less important. Sometimes, when you are doing significant inline server side processing java certainly has a noticeable speed advantage (as i mentioned in the blog the java 7 escape based optimisations are very impressive). Sites like this are a minority though i think.

    —–

    hi lincoln – yes – a smarter way of caching for development is probably the first things to be added. we have put what we have out there ASAP as we think it will be valuable to other JSF users battling to get acceptable performance, and to get some feedback on any possibly issues we have missed.

    i have a few other ideas:

    - there’s no reason why there should be any overhead difference between small and large views post creation. farming the post render view cleaning to a worker thread would allow the client to return immediately and keep inline non render overhead sub millisecond in all cases.
    - to allow JSTL tags to be used it would be good to make provision for a discriminator key derived from a request parameter, so the same page can be pooled under different keys to cater for these JSTL alterations and not cross-infect the cache.
    - it would be nice to compile a list of all components from the major libraries that do not satisfy the stateless requirements and flag an error when placed in a stateless page so users don’t inadvertently leak data by switching to stateless.
    - a hash comparison of some sort to ensure views are not being mutated when being put back in the pool.

    at the end of the day we are Sydney IT consultants. we wrote this module to significantly push forward the performance of complex JSF based applications of our clients – some have invested many millions of dollars in the technology and staff training. i’m sure there are many others in the same boat. worst case we will continue to maintain it as required for our own needs but obviously community buy-in is preferable.

    we are not experts in the mojarra code base and it would be great to give commit writes to someone who’s in the JSF development loop to help drive this. it would be nice to see a stateless option added to mojarra itself.

    if anyone’s interested to help please contact us.

    regards Rudi, IndustrieIT

  7. Nitin says:

    Thank you.
    The message is clear: jsf (server side processing for client) may not be acceptable in current situations where JS/JQ has seized the web.
    Please guide us what would be an ideal server side web programming language in today’s scenario. I still feel Java holds top ranks (in processing / loading speed) as compared to the popular scripting languages like Ruby or Java powered languages like Scala.

  8. gonzalad says:

    Very interesting and should be very usefull for most JSF apps.

    IMO, this should go in pair with http://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-941 (if c:if isn’t anymore usable, rendered attribute performance will be a blocker for common use cases – i.e. conditionnal line display in table component).

  9. Very nice article and project! If I didn’t use view-cutting via JSTL tags so thoroughly I’d give it a run in my current project.

    Another thing to watch out for performance-wise is memory leaks through UIComponent fields. For example, some datatables cache the result set in a field, which would never be freed when the view never expires (though the blame for this lies more with the component author than with JSF) .

  10. Rudi Simic says:

    BETA 2 RELEASED…

    https://bitbucket.org/industrieit/stateless-jsf/downloads

    view cleanup has been moved out of band to a worker thread to allow the HTTP service thread to return immediately.

    Framework overhead on a GET (time outside of Component.render()) should now be sub millisecond on the inline thread regardless of view size.

    Partial postbacks (such as execute=”@this” with a small render region) are also very fast – chrome dev tools sometimes can’t measure the latency.

    Next item on the agenda is a discriminator key to allow some JSTL modification of the views.

    Rudi…

  11. Great work!

    IMO the JSF state is a big design flaw of JavaServer Faces, and I very much agree with you that without it, JSF is a lot faster. But apart from the performance impact, JSF would be a lot cleaner and maybe easier to use/understand for developers without the state. However, it is a design flaw that kept growing and now it is the basis of a lot of JSF applications and, of course, frameworks.

    Fortunately, as the better GET support was introduced in JSF 2.0, the first step was taken towards getting rid of the state (there is no state in GET requests). However, the state is still there for every POST or AJAX request (there is not even an AJAX-GET request, meaning AJAX without submitting the current state). And this is certainly a very important thing that should be changed in future versions of JSF.

    So once again, good job on the article!

    Jakob

  12. Rudi Simic says:

    STATELESS JSF BETA 3 RELEASED…

    https://bitbucket.org/industrieit/stateless-jsf/downloads

    Although some internal refinement was done since the original beta release, BETA3 adds one extra page configuration attribute to cater for JSTL – what i call a discriminator.

    Note that this is more for backwards campatibility to support old pages. As specified in the article, view size has negligible performance penalty in stateless mode, so there is no need to use JSTL to clip the tree. I recommend you do not use JSTL at all for stateless new pages – use ui:fragment rather than c:if unless you know what you are doing.

    If you want to support an old page with JSTL in stateless mode, here’s how to make use of the discriminator:

    include the discriminator attribute in the stateless marker component as such:

    ….h:panelGroup id=”SJSF” rendered=”false” stateless=”true” discriminator=”sampleController.discriminator”….

    a sample discriminator is included in the stateless test page.

    the discriminator value is implicit el – do not explicitly include the #{…} braces – they’ll be added for you. The discriminator expression should call a method that returns a string. This string is used to append to the cache key for the view, so that the view can be stored under multiple independent keys.

    The discriminator is optional.

    The bottom of the sample page shows cache stats (the number indicates how many views are pooled) for the stateless view pool (use this during dev to ensure the discriminators are operating as expected):

    STATELESS CACHE STATS:
    /statelessjsf/sampleStateless.htm=7
    /statelessjsf/sampleStateless.htm-B=6
    /statelessjsf/sampleStateless.htm-A=5

    the appended ‘-A’ and ‘-B’ values indicate the view is stored with no discriminator value (or a value of null), plus two discriminator values of ‘A’ and ‘B’.

    Imagine if you have a page that used JSTL c:if tags to include certain sections for admin users. the c:if test attribute may well be calling an el method called #{user.isAdmin()}. If that was the only value which discriminates the view, you could define a method called getUserType() which returns teh strings’admin’, or ‘normal’

    the marker component would then have a discriminator tag of

    discriminator=”user.getUserType()” [NOTE - DO NOT INCLUDE THE BRACING, IT'S IMPLIED]

    your page will then be mapped under two differ keys similar to “/mypage.jsf-admin” and “mypage.jsf-normal”

    the discriminator value is evaluated once at phase 1 – the view shouldn’t switch to a different discriminator during a post.

    note that if you are thinking of a discriminator like ‘user.userName’ you’re on the wrong track – its highly unlikely your page is changed for each individual user.

    a page with two discriminating variables will require a discriminator string which has values which are a cartesian product of all possible combinations. in cases where this gets too high, the stateless cache itself may get too big and you should modify the actual page instead (you may well just be able to change each …c:if test=”#{X}”… to …ui:fragment rendered=”#{X}”…

    the test page derives its discriminator vaue from a query param – try:

    sampleStateless.htm?discrim=A

    obviously doing something like this in a live site may be silly (let the user choose if they are an admin?). it’s just for demonstration purposes.

    The default cache buffer size is 5. In the event where a rush of concurrent requests requires more views, they will be created. The cache will then slowly contract back to 6 (at a rate increasing the bigger it gets – entry 7 is removed after 60 seconds, 8 slightly quicker etc, in an inverse geometric relationship). The buffer of five allows a steady concurrent load with minimal memory.

    BETA 3 will probably be the last non final release. With the async view cleanup added in BETA2 we have achieved a sub millisecond non render GET overhead. I can’t think af anything else that will make things appreciably faster.

    Rudi…

  13. Rudi Simic says:

    STATELESS JSF BETA 4 RELEASED

    https://bitbucket.org/industrieit/stateless-jsf/downloads

    fix for ‘last post’ problem. you can’t call creatview on an ajax postback – it must come from the pool. in cases where ajax postbacks are the majority of requests, its possible for the cache to be emptied at which point there is no recourse to manufacture a new view. in previous releases a pool was created where a low water mark is set that only accepts postbacks, whereas other requests would create a new view even if the pool was not empty. the pool could still be run down in a worst case scenario however.

    in beta 4 this possibility is closed off. in the case where a postback asks for the last view in the pool, we use the robust-it cloning library to deep clone the last item so we always have a template to create a new view for a postback in all load situations. its slower than createview so we still have a postback pool allowance in preference, and cloning is still only for the rare high load corner cases.

    all views must still be seeded by a get request however, before postbacks can be accepted.

    rudi…

  14. Oleg says:

    Hi Rudi,

    Great article, good approach. I have large views. Ufortunately, I would like to get rid of > 100 subviews controlled by rendered=”true/false” attributes. I prefer dynamic includes with ui:include. It’s possible with the last Mojarra releases to modify filename (“src” attribute) in ui:include to include pages dynamically. Stateless JSF doesn’t allow this way of including because AddToView event is only fired once. Right? Do you mean putting a view in many branches that are conditionally rendered is a good approach without side effects? The view gets bigger then.

    Thanks for your reply in advance.

    • Rudi Simic says:

      hi oleg.

      excessive conditional rendering is a big performance killer with normal stateful jsf but not stateless jsf. multiple fragments conditionally rendered is the generally the right way to do it stateless. it doesn’t really matter how big the tree is in stateless mode as its only created once. that’s not to say you should write the whole app as one page (though you could) – obviously split up into functional pages to support bookmarking and searchability. but don’t truncate or split pages which are a logical functional boundary for performance reasons (you generally must with stateful jsf but not necessary stateless).

      please have a look at the comment above regarding beta 3 and the discriminator functionality.

      if you choose to use JSTL and/or dynamic imports that depend on a small number of variables, an appropriate discriminator will cache the views for one page under multiple keys to cater for these discrete alternate tree creations. you can still run efficiently stateless provided there aren’t TOO many discriminator key combinations. see the release comment and the sample page for an example.

      regards, rudi…

      • Oleg says:

        Hi Rudi,

        That sounds good. I don’t plan to use JSTL at all. JSTL is evil :-) I will look deeper in your implementation. Thanks.

        Just two questions. 1) I have understood that we can’t use view scoped beans with stateless JSF. Right? What would be an alternative then? Some stuff can’t be session scoped and request scope is too narrow. 2) Do you have your Maven artefact in the Maven Central repo or any other Maven repo?

        Best regards.

  15. Rudi Simic says:

    oleg – not in maven yet i’ll put it in when i release the RC and final.

    i don’t like viewscope as explained in the questions but here’s a sample quasi view map functionality that can be used with stateless jsf

    just under your jsf form tag include a raw HTML hidden input (NOT a JSF input)


    …h:form…
    …input type=”hidden” name=”viewid” value=”#{viewcontroller.viewId}”….

    create a stateless controller class (which i named ‘viewcontroller) and add two methods:

    public String getViewId()
    {
    FacesContext fc=FacesContext.getCurrentInstance();
    String viewid=fc.getExternalContext().getRequestParameterMap().get(“viewid”);
    if (viewid==null)
    {
    viewid=”"+new Random().nextInt();
    fc.getExternalContext().getRequestParameterMap().put(“viewid”, viewid);
    }
    return viewid;
    }

    public Map getViewMap()
    {
    FacesContext fc=FacesContext.getCurrentInstance();
    String viewattr=”jsf_view”+getViewId();
    Map viewmap=(Map) fc.getExternalContext().getSessionMap().get(viewattr);
    if (viewmap==null)
    {
    viewmap=new HashMap();
    fc.getExternalContext().getSessionMap().put(viewattr, viewmap);
    }
    return viewmap;
    }

    the hidden viewid field will be seeded once. any postback will then include it as a html parameter which can be retrieved from the externalcontext on any postback (ajax or immediate or not)

    once seeded the viewid parameter value oscillates between server and client indefinitely during an unbroken postback chain, yet is not retained in the viewroot. you use this id as a key into the session.

    if you are using seam or cdi you could then use the factory pattern to wrap up individual bean names so they can be injected via annotations

    seam conversations would be better – but not working yet and i will not fix till seam 2.3 is released

    • Thomas says:

      Why seam conversation wont work?
      What about ViewAccessScoped of MyFaces CODI?

      • Rudi Simic says:

        seam conversations don’t fully work with normal jsf 2, as seam 2 isn’t fully supported yet on jsf 2. since i am further modifying the jsf 2 lifecycle it works even less on stateless jsf 2 and i do not want to trry and figure it out till 2.3 is closer to completion. ideally it would be nice if the seam guys did it.

        i’ve tried to elucidate in the blog why view scoped beans, that are stored in the view, are a bad idea when we are recycling the views to serve potentially limitless requests from other users. a view no longer belongs to a particular user. it belongs to the application.

        i don’t know anything about myfaces, sorry, but implementation should not matter – do not use view scoped beans if you are running in stateless mode.

        if you MUST have a scope like view scope – read my response to oleg for a possible workaround implementation

  16. Karsten Torp says:

    Hello Rudi.

    First of all, thanks for investing time in this. I like JSF and the only major problem I have with JSF is the performance.

    You have created a good show case that exposes and explains the performance bottle neck in JSF. This is great because it can be used by other parties to discuss JSF performance (and the lag of performance) and move JSF forward. IMO this is as significant as the concrete solution you have implemented because it shows that there is a huge problem.

    Now regarding the actual implementation, you mention in your last post that conversations will not work until Seam 2.3. This gives me hope that I can actually start using stateless views once I have migrated from Seam 2.2 to Seam 2.3 and upgraded from JSF 1.2 to JSF 2. Is this being coordinated with Marek Novotny or someone else from the Seam2 team and have you tested it with one of the builds of Seam 2.3?

    Thanks,

    Karsten.

    • Rudi Simic says:

      hi karsten.

      seam 2 has a few quirks with JSF 2, and it won’t officially be supported till seam 2.3. nevertheless we are using it in prod/stateful jsf with a modified seam.jar (remove the faces-config.xml file from the jar) and it mostly all works. the seam files are in the project zip. unlike cdi, seam 2 really couples into jsf, so it has to be adapted for JSF2 and likely will have to be adapted again for statelss jsf 2. no i haven’t tried the pre release builds as yet.

      i see redhat’s been scouting around from the server logs, but i don’t know if the seam guys know of our existence. it would be good if marek got seam 2.3 working flawlessly with stateless as it would a great shrink wrapped package. feel free to advocate.

      regarding earlier versions of jsf – i have been getting some queries regarding this so i may release a stateless version for jsf 1.2 as well. it should be a simple port

  17. Thomas says:

    Hi Rudi,

    i think i found an bug.
    If you visit the stateless page with an discriminator, and without visiting the page without discriminator before, a NPE will be throwed.

    Just restart your tomcat/jetty and visit http://localhost:8080/sampleStateless.htm?discrim=A (do not open the page without discriminator before) and click on a link.

    Best regards
    Thomas

    • Rudi Simic says:

      hi thomas.
      it’s not a bug (was wondering if anyone would notice)

      i used a url query parameter as a discriminator to make it easy to demonstrate, but it’s not really appropriate. the parameter obviously is only included in GETS, and will not be included in a postback by default (you’d have to nest a h:param tag inside any postback link – same problem when using seam conversationsif not using the seam links)

      what we are doing is essentially switching discriminators on a postback which is a no-no (well, you can do it if you know what you are doing and the other discriminator is seeded but it won’t work in ALL situations). in this case it would have worked, but the null discriminator version of the page was not seeded with a GET beforehand.

      a discriminator that stays stable between gets and posts would not have this problem (such as something deriving from a preset session variable for example)

      regards,
      rudi…

      • Thomas says:

        Hi rudy,

        ok, i understand!
        Then i sucessfully refactored your code and it’s now working with MyFaces and Mojarra. We need just a different ViewDeclarationLanguageFactory which can be switched via different faces-config in seperated myfaces and mojarra sub-modules :)

        Best regards
        Thomas

  18. Jonathan Tougas says:

    Why get rid of view state entirely if it the view creation that’s problematic? Would it be possible to short-circuit the view creation process to return a view from a pool instead of creating a new one, and back the viewstate with a map in the session instead of the viewroot?

    • Rudi Simic says:

      hi jonathan.

      the reason is because it’s not just the view creation thats problematic. the constant view creation accounts for the appalling cpu load of jsf.

      the other issue i mentioned is excessive server memory allocation to store the serialised viewstate. if this were done in a very efficient manner it would not necessarily be that bad. but the current implementation is woeful – even with delta storage implemented in JSF 2.

      the whole idea of stateless JSF is ZERO view state. application state can always be accessed from backing beans fully under your control.

      there are many components that implicitly persist to the view with no option to flush to beans. these should not be used in statelss mode.

      there is a jira ticket to provide a statelss mode in a future version of JSF, if it were to be implemented these components would be altered.