lunes, 13 de enero de 2014

What's new in MyFaces 2.2

JSF 2.2 spec was released around March/April of 2013. Over the last year (2013), the attention of MyFaces community has been on deliver a robust and compliant JSF implementation. In the end of October 2013, it was released a new beta, which includes 100% of the features required by the spec. An official release of MyFaces Core 2.2.0 has been released recently (January 2014), but on the way some new and interesting features has been added (besides what's new in JSF 2.2) that are worth to mention. Some of them are completely new, and some others has been added based on the interpretation done of the new spec.

View Pooling (Going beyond JSF 2.2 stateless views)

 

In JSF 2.2 now it is possible to define a view as "stateless" just writing something like this on the top level page:

<f:view transient="true" ...>

but the research done in MyFaces community has led to the conclusion that from performance perspective, there is no a real gain in speed or memory by multiple reasons:
  • The size of a view in the session is very small.
  • Save or restore the state is quite fast, compared with the work spent creating or rendering the view.
  • The view still needs to be built.
In my personal opinion, it is better to let JSF handle the state problem and don't use stateless views at all. But on the way, it was found a way to reuse JSF views effectively and get a good improvement in performance, adding some additional complexity at the time to create components. Please note MyFaces Core even without the view pool gives a very good performance, so most users will not bother about enable this feature, but for some others this can be useful.

There are two ways to enable this feature:


1. Add an entry into a faces-config.xml file like this:

    <faces-config-extension>
        <view-pool-mapping>
            <url-pattern>/*</url-pattern>
            <parameter>

                <name>org.apache.myfaces.VIEW_POOL_MAX_POOL_SIZE</name>
                <value>5</value>
            </parameter>
        </view-pool-mapping>
    </faces-config-extension>


With this mode you can override the global web config parameters.
   
2. Encapsulate your top level page with

<f:view oamEnableViewPool=true>

A previous blog talks about the fundamentals of the technique. Please note third party libraries needs to be compatible with view pooling, so for now only the components included in JSF 2.2 and some MyFaces Tomahawk components support this mode.


SPI intefaces for custom flow and view scope

 

Many members of MyFaces community prefer use CDI and specially Apache OpenWebBeans and Apache TomEE for its projects, but the community is also aware of people who use other alternate technologies. In JSF 2.2 some CDI annotations were added like @FlowScoped and @ViewScoped, but it was not provided a general solution for users who don't want or can use CDI. In Myfaces 2.2 we have added the following SPI interfaces:

  • org.apache.myfaces.spi.ViewScopeProvider
  • org.apache.myfaces.spi.FacesFlowProvider

In that way it is possible to fill the gap and create implementations of those scopes. Inside MyFaces code there are 2 implementations of each SPI interface, one using CDI and one without CDI, so I hope it will be easy for the interested developers to fill the gap according to their needs.

Compatibility mode for Facelets 1.1.x / Mojarra syntax

 

In Facelets 1.1.x and in current versions of Mojarra, there is still some tags that does not behave properly. For example:
  • Declarations like  <c:set var="..." value="..."> applies for everything below the declaration and pass through any facelet, including composite components, breaking encapsulation principle.
  • <ui:param ...> implementation is the same as <c:set ...>, and it should theorically add a template scope parameter.
  • <ui:include ...> is not isolated properly, mixing declarations of <ui:define ...> and <ui:insert ...> from outer levels. In cases where this is valid <ui:decorate ...> should be used instead.
In MyFaces Core 2.0.x/2.1.x the previous problems were fixed and a proper syntax was introduced. This is necessary for improvements like EL expression caching and view pooling, but some users found these differences annoying specially when they try to migrate from Mojarra to MyFaces.

With this web config parameter:

<context-param>
    <param-name>org.apache.myfaces.STRICT_JSF_2_FACELETS_COMPATIBILITY</param-name>
    <param-value>true</param-value>

</context-param>


A special mode is enabled that allows facelets 1.1.x / Mojarra ugly syntax. Anyway, I encourage users to fix their apps and use the syntax available in MyFaces, because it follows the spec more strictly and it keeps compatibility with Mojarra. But keep in mind, from MyFaces perspective, the current syntax in Mojarra does not follow the spec wording.

Partial State Saving algorithm is applied even in dynamic sections and programatically created components

 

The current algorithm implemented inside MyFaces 2.2 uses Partial State Saving (PSS) technique in every possible situation:
  •  Using dynamic facelet tags like <c:if ...>, <c:choose ...>, <c:forEach>, <ui:include src="#{...}">, <ui:decorate template="#{...}"> or <ui:composition template="#{...}">.
  • Composite components that use <cc:insertChildren ...> or <cc:insertFacet ...>
  • Components created by effect of ViewDeclarationLanguage.createComponent(...)
The perceived effect compared for example with Mojarra is a reduction in some cases of 80%-90% of the session size used or even more according to the view design and the components used, which lead to an optimal performance level never seen before.

ViewDeclarationLanguage.createComponent(...)  supports non JSF component tags

 

ViewDeclarationLanguage.createComponent(...) was added in JSF 2.2 to allow create composite components programatically. But it is possible to extend that syntax a little bit to allow use other non component tags like <ui:include ...> as if they were components. For example:

ViewDeclarationLanguage vdl = facesContext.getApplication().
    getViewHandler().getViewDeclarationLanguage(
        facesContext, facesContext.getViewRoot().getViewId());

Map<String, Object> attributes = new HashMap<String, Object>();
attributes.put("src", "/addSimpleIncludeVDL_1_1.xhtml");
UIComponent component = vdl.createComponent(facesContext,
    "http://java.sun.com/jsf/facelets",
    "include", attributes);
panel.getChildren().add(component);


The idea is create automatically a wrapper component when it is necessary. In this way it is possible to avoid a hack over FaceletFactory that in my opinion it will never work well.

<c:forEach ...> has been fixed once for all

 

It is well known that <c:forEach> tags sometimes does not work as it should. For example, if the collection iterated by <c:forEach> tag changes somehow, the state of the inner components are not restored correctly. The reason is the original algorithm from facelets 1.1.x don't include the necessary logic to deal with this problem, and it was required many big changes inside facelets algorithm before make an attempt to fix it. In MyFaces 2.2.0 we finally have all necessary changes in place, so the long awaited fix has been finally done. The only thing you need to remember is, the elements in the iterated collection must be Serializable and implement hashCode() and equals(...) method properly, otherwise the old algorithm is used.

This tag has been also aligned with PSS algorithm, so now it is possible to use it in combination to dynamic facelet tags and keep the state small. Please remember in previous versions of MyFaces Core, the components created by effect of <c:forEach> tag needs to be saved and restored fully. See MYFACES-3811  for details.

View slots are reused for ajax request and the information stored in view scope is discarded when the view is removed from state on server side state saving

 

In MyFaces Core 2.0 and 2.1, each ajax request requires one slot in the view storage on server side state saving. A change was added to reuse view slots in those cases, reducing the space required in session, and in that way make a better use of the available space.

Additionally, it was included an algorithm that detect and discard view scopes when they are no longer used, keeping the session size as small as possible.

Early Flush for resources inside <head> or <h:head> tag

 

Using the following web config parameter:


<context-param>
    <param-name>org.apache.myfaces.EARLY_FLUSH_ENABLED</param-name>
    <param-value>true</param-value>

</context-param>

flush all resources that are rendered in html <head> tag early, which allows web browsers to fetch them as soon as the flush is done but while the page is loaded, improving response time.

CDI Injection for Converter and Validators

 

Using these two web config parameters:

<context-param>
    <param-name>org.apache.myfaces.CDI_MANAGED_CONVERTERS_ENABLED</param-name>
    <param-value>true</param-value>

</context-param>

<context-param>
    <param-name>org.apache.myfaces.CDI_MANAGED_VALIDATORS_ENABLED</param-name>
    <param-value>true</param-value>

</context-param>

MyFaces activates a built-in mode that enables CDI Injection for JSF Converters and Validators. This was implemented using an override over Application.createConverter(...) and Application.createValidator(...).

For example:

@FacesConverter("cdiConverter")
public class ConverterAsCdiBean implements Converter {

    @Inject
    private ConverterService converterService;


   /*... */
}

in the page:



<h:inputText id="name" value="#{helloWorld.name}" required="true">
    <f:converter converterId="cdiConverter"/>
</h:inputText>


That's it. But there are some considerations:
  • JSF use a wrapper around the converter/validator to keep control of the instantiation or lookup, but you can get the real instance through a cast to FacesWrapper and calling getWrapped(). 
  • The lifetime of a converter like the one from the example by default is request scope, because in this case CDI manages the lifecycle of the converter/validator, so in that sense it is detached from the view. For example, by default @PostConstruct and @PreDestroy are called at each request.

TomEE 1.6.x compatibility

 

The code has been done in a way that allow run 2.2.0 artifacts in TomEE 1.6.x containers. In other words, the easiest way to try MyFaces Core 2.2.0 jars is just take a distribution of TomEE 1.6.x from the download page and replace the 2.1.x jars with the new ones. As simple as that!.

jueves, 12 de diciembre de 2013

View Pooling in JSF 2.2 using Apache MyFaces

There has been a lot of ideas about how can we improve MyFaces performance to make it even better. A lot of improvements has been done over the time, but the last effort to do in this area was left for 2.2. This article contains the DRAFT about how View Pooling could work in MyFaces Core, which is a feature thought to provide the best possible performance and that it could be avalable for version 2.2.0 and upper.

Background


The idea of the view pool comes from ideas of the community about how to improve JSF performance and the speculation behind how the state affects performance in web frameworks. The primary perception was that a stateful web framework by definition does not have a good performance and a stateless web framework can be faster, because a stateful web framework needs to deal with the "state" problem and that logic can expensive according to how it is implemented.

But that way to see the problem is completely wrong, because in practice there are other things that can affect performance more significantly and with a good design it is possible to improve things to a very good level. Proof of that is with the introduction of JSF 2.0 Partial State Saving (PSS), the perception changed, because it was demostrated that it is possible to reduce the state size used by the views of an application.

In JSF 2.2 another step forward has been done with the introduction of  "stateless JSF". The idea is just  mark the views in the application that does not require state to work properly, and then skip the state saving and restoring algorithm to improve performance. It works for Mojarra but it doesn't have any effect with MyFaces because its PSS algorithm has been carefully designed and improved over a long time, and it is very efficient at the time of restore and save the state.

If the state is not the problem, or in other words, if the state calculation does not have a significant impact over performance, which one is the real problem? is there any problem?. The evidence gathered suggest there is not any problem, and the proof is that an application using MyFaces is very near in terms of performance than the same application written with hardcoded Servlets and JSP.

Why the solution using Servlets and JSP is the fastest one? There are two fundamental reasons:
  • Everything should be written by hand, so there is no abstraction layer and in that way there is no overhead imposed by that layer.
  •  It uses the minimum possible amount of memory.
Please remember JSP pages are compiled into a servlet. The servlet creates a JSP tag tree and then this tree is processed. The result is most of the objects used by JSP are static constants. Technically nothing will be as fast as Servlet/JSP. But the objective is not be the fastest framework. Instead, the objective is be as fast as possible without sacrifice the abstraction layer that provides JSF.

From other point of view, some tests done long time ago about JSF lifecycle and its performance in MyFaces suggest the following conclusions:
  • Render the response involves about 70% of the processing time used by JSF.
  • Build the view involves about 15%-20% of the processing time used by JSF.
  • The time spent in traverse the component tree is a lot less than the time spent rendering the response or building the view.
  • In ajax request, the relative time spent building the view can have more weight over the overall response time according to the size of the component tree and the operations involved in process the response.
According to the previous analysis, it is possible to improve the way how views are built to get better response times. There are some options:
  • Use "static" views, or in other words, stateless views that can be used across multiple threads concurrently.
  • Find a way to reuse the views.
The first option is not a good solution, because anyway there is some information that is inside UIComponent and should be stored per thread, and precisely UIComponent is a place specifically designed to store that information. In fact, the first option is not really an option and it was discarded after some attempts.

A new way to reuse views


Build a view can be described as a repetitive calculation. Many components are created and assembled in a predictable way with attributes that most of them are defined to their associated templates or facelets.

In JSF 2.0, PSS algorithm takes advantage of that predictable behavior and make a distinction between the "initial state" and the "delta state". In this way, a view is a composition of the initial state and its delta state. But in the same way, if it is substracted the delta from the current state, the result is the initial state. So, if we can somehow "substract" or "reset" the delta from the current state, we could derive a view into its initial state in the same way as a view is created from scratch.

In other words, we are taking advantage of the current JSF spec and we are taking it to the next level. PSS algorithm can be used to check if a view has been modified or not, checking its state. That information can help us to decide if a component is reusable (no state) or not (with state). If the component has state, the idea is reset the state and get it back to the initial state defined by the first call of markInitialState().

This can be done quite easily adding a context attribute "oam.view.resetSaveStateMode" and checking the value of that attribute and take proper actions into saveState() method. There are two modes: soft reset [1] and hard reset [2]. A soft reset clears the "transient" state or those internal attributes used by the component but it does not clear the "delta" state. A hard reset destroy both the "transient" state and the "delta" state. If the component cannot be reset, saveState() should return a non null value.

If a component in a view cannot be reset fully, it is possible to just remove the component from the tree and use facelets refreshing algorithm to rebuild the missing part and reuse a view partially.

But according to the spec, create a full view involves the following steps:
  • Call vdl.createMetadataView(facesContext) and call internally ViewHandler.createView(...) or just call ViewHandler.createView(...) 
  • Call vdl.buildView(...)
In the case of UIViewRoot, we can just take a "snapshot" of the component and exclude it from the reuse step. So the view pool does not reuse the root node but all the children, excluding the content of f:metadata facet.

There exists 4 fundamental attributes that define a view in JSF:
  • viewId
  • locale
  • renderKitId
  • contracts
This means if a view has the same values for the previous attributes, we can consider the structure is the same and the view can be reused partially or fully. The pool uses these attributes as a key to group similar views, so there are different sets of views according to these values.

But a view can have a different structure too if it is used one of the following facelets tags.
  • <c:if ...>
  • <c:choose ...>
  • <ui:include src="#{...}" ...>
  • <ui:decorate template="#{...}" ...>
  • <c:forEach ...>
According to its dynamic behavior, views can be classified into two groups: "static structure views" and "dynamic structure views". This distinction is important because dynamic structure views requires a special treatement.

There are two basic operation that any pool must do: create objects and store them in the pool and take the objects from the pool. In the JSF lifecycle, there are the following points where the pool must take some action:
  • At the first request, the view and the view metadata are created on restore view phase. Later, the view is filled when vdl.buildView(...) is called on render response phase. In this moment the algorithm can take a view from the pool. Here there are three cases:

  1.  If the view is partial it requires to be refreshed by the vdl to restore the missing parts.
  2. If the view is complete but dynamic, since we don't know how the dynamic portion of the view can change, it falls in the same case as a partial view and it should be refreshed by the vdl.
  3. If the view is complete but static, the view is ready to use.

  • If the view does not require state saving (does not contains h:form instances), after the view is rendered we can do a hard reset over the view and store it into the pool. In other words, we just discard the transient and delta state from the view, calling vdl.saveState(...). In a strict sense, in vdl.saveState(...) under hard reset mode, no state is saved but the view is stored into the pool.
  • If the view requires state saving, the algorithm will call StateManager.saveState(...) and in that way vdl.saveState(...) . In this point the algorithm saves the delta state, reset the view and store it into the pool.
  • In a postback, when the view is restored (StateManagementStrategy.restoreView), we can try to extract the dynamic portion of the view from the state. If there is no dynamic state, the view is static and the inner call of vdl.buildView will take it from the pool. If there is dynamic state, we can take a dynamic view from the pool using the dynamic state.
  • When there is a navigation, there is a way to store the view that is left behind into the pool. The idea is change the default ActionListenerImpl and ensure handleNavigation() is called before the end of the current phase, or in other words doing a "deferred navigation". This is necessary to ensure the view is in a stable state, because the ActionListener is activated while the tree is traversed. By default this behavior is disabled.

Configuration


The pool has the following web config parameters:
  • org.apache.myfaces.VIEW_POOL_MAX_POOL_SIZE : Indicates the number of views stored in the pool per key.
  • org.apache.myfaces.VIEW_POOL_MAX_DYNAMIC_PARTIAL_LIMIT : Indicates the number of dynamic views that can be reused as partial views.
  • org.apache.myfaces.VIEW_POOL_ENTRY_MODE : Indicates how the view is hold by a "soft" or a "weak" reference into the pool. It affects how GC collects the views.
  • org.apache.myfaces.VIEW_POOL_DEFERRED_NAVIGATION : reuse views that are navigated using default algorithm (increase reusal but it uses a hack that does not follow jsf spec) ).
There are two ways to enable a view to be used by the view pool:

1. Add an entry into a faces-config.xml file like this:

    <faces-config-extension>
        <view-pool-mapping>
            <url-pattern>/*</url-pattern>
            <parameter>

                <name>org.apache.myfaces.VIEW_POOL_MAX_POOL_SIZE</name>
                <value>5</value>
            </parameter>
        </view-pool-mapping>
    </faces-config-extension>

With this mode you can override the global web config parameters.
   
2. Encapsulate your top level page with

<f:view oamEnableViewPool=true>

Note if the view is marked as "transient" or stateless and poolable at the same time the view pool will disabled, because the view pool reuse the state saving algorithm.

Final Thoughts and Conclusions

The disadvantages of the view pooling technique are:
  • All components used in a view that uses view pooling must be compatible with the technique. The reason is some components has some variables that are not part of the state, but plays an important role. For example, in UIData there is a variable used to hold the dataModel and if a reset is required, the model must be cleared. In other cases, since all state is contained in the inner StateHelper instance provided by MyFaces implementation through UIComponentBase, there is no need to do anything else to make it compatible. If a component extends from UIComponent directly, it should add the necessary code to reset the view in saveState(...) method.
  • The view pool uses state saving algorithm to decide if a view is reusable or not, but this detection technique is not 100% failsafe if the component is not compatible.
  •  Listeners subscribed using a facelet tag handler that invokes UIViewRoot.subscribeToViewEvent(...) may not work as expected, because the tag handler is not executed at each request, and these listeners are not saved/restored with the view state and needs to be subscribed at each request.
The following improvements has been confirmed after some performance tests done with the know demo application used in the performance comparison:
  • A reduction of 25% of the transient memory used, which means a lot less memory is used and it is used at a slower pace. It also means less GC calls and a better CPU usage.
  • An improvement of 9% over throughput for non ajax requests. 
  • An improvement from 9% to 30% or even more for ajax request, according to the tree size.
Note these measures depends on the application studied but it can give an idea about what to expect.

My recommendation is first evaluate your application requeriments and use this technique only in cases where performance is a critical concern. Most of the time an application using MyFaces without the view pool is good enough. It is a good idea to select the views that receives the higher load and use the pool in only those cases, but that decision depends on the available memory and the load you application must face. If the view is too dynamic, disable the pool could give better results.

At last, just try it and let us know your opinion in Apache MyFaces dev and users mailing list.

domingo, 2 de junio de 2013

Coming soon: Web Framework Comparison between JSF 2, Spring MVC, Tapestry, Grails 2 and Wicket

In the last months, I have been working on update and expand the web framework comparison to include more frameworks, like JSF 2, Spring MVC (using JSP and Thymeleaf), Tapestry, Grails 2 and Wicket.
 
The intention has been to provide a fair, detailed and accurate comparison. Not only publish some information or draw some graphs from nowhere, but provide details about where the data came from and give the readers the chance to try things for yourselves. In that way, other teams involved can check the demo applications and see if the applications are correct or maybe propose changes.

I hope the demo applications can be useful to people that just wants to see how some typical tasks are done using a specified web framework.

One of the big failures other people has done in web framework comparisons before, has been do not take into account the particularities involved in each web framework. Guess what: in real life the small details really matters, and can change the whole picture very quickly.

The comparison has lots of complex details, but to make it easier for the readers, I'm working on create a series of articles in JSFCentral that describes all work done and resume the previous comparison between JSF 2 and Wicket.

See:

Article about web framework comparison at JSFCentral Part 1
Article about web framework comparison at JSFCentral Part 2

Keep tuned, I hope the article will go out soon :-) .

miércoles, 5 de diciembre de 2012

HTML white space compression for JSF using MyFaces and Facelets

In MyFaces Core another nice feature was introduced since version 2.1.10. The idea is quite simple, just try to minimize the additional white spaces in a html page to reduce its size. Usually the code generated by renderers does not contains unnecessary spaces, but the code that comes directly from html markup in facelets comes straight from the xhtml or xml file used.

The trick behind this feature is enable/disable it as a do inside facelets compiler option. Just add this into your WEB-INF/faces-config.xml  file:


<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
                         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_1.xsd"
                         version="2.1">
<faces-config-extension>
    <facelets-processing>
        <file-extension>.xhtml</file-extension>
        <process-as>xhtml</process-as>
        <oam-compress-spaces>true</oam-compress-spaces>
    </facelets-processing>
</faces-config> 


That's it. Now, facelets compiler will try to reduce or remove spaces/tabs when they are not necessary, following the rules for html white space compression, to avoid change the apperance of the page. In simple words, this means when necessary it replace multiple continuous spaces with just one or remove all of them. It also try to use '\n' characters when possible, to make easier read the page markup once compressed.

Since this optimization is done in facelets compiler, the effort to reduce white spaces is just done once, so all your pages will not impose additional CPU or memory overhead. It's more, it reduce the memory and CPU resources required to render a page, so this can give a little boost to your application.

Note this only affects the spaces generated by plain html markup, if you have a component renderer that output some spaces, those ones are not preprocessed.

viernes, 18 de mayo de 2012

Understanding JSF 2 and Wicket: Performance Comparison

See the updated comparison for 2013 at JSFCentral:


Suggestions, comments, critics or any discussion about it can be posted below.

----------------------------------------------------------------------------------------------

Performance is important in a web framework, even though it is certainly not the only consideration. But anyway, it is a topic that deserves an in-deep analysis. This is not a topic that can be reduced to just some few numbers, instead, web frameworks try to make a balance performance and other aspects like usability, extensibility, and much more.

In the last year (2011-2012), a lot of performance improvements has been done inside Apache MyFaces JSF Implementation (aka MyFaces Core). To see how good are the improvements, a comparison was done against a similar Java Web Framework like Wicket. In order to save some work, the reference application provided in this link was used:


Fortunately, the wicket guys have been so kind to updated the original application running with 1.4.x to version 1.5.x, so we'll compare JSF against two Wicket versions (1.4.20 and 1.5.5). A comparison against Tapestry might happen later. In the end, the intention is to look at how JSF works from a performance perspective, so Wicket will be taken only as a reference point.

Checking the code provided in that blog and the related data, some rather serious problems were discovered. Anyway, the code example is good enough to reuse it, while obviously fixing the detected problems. The updated code, configuration used, detailed documentation and experimental data can be found in the internet (github).


Detailed Document (21 pages, PDF Format)


Keep in mind that this blog entry is just a resume of the detailed document.

A good benchmark should consider different aspects. So, for this comparison, the following aspects has been checked:
  • Speed benchmark: Check the speed of the code under different situations.
  • Memory Consumption : Involves checking how much memory does the application need to allocate for a specific task, and how the application behaves under low memory conditions.
  • Session Size : Check how much memory is used to store the session.
It is quite obvious why these three aspects should be considered:
  • If the framework is fast it will process more requests with less CPU consumption.
  • If the framework requires less memory, less time will be used in garbage collection and the framework will perform better under stress conditions.
  • If it uses less memory as session storage, it will be able to serve more users with the same memory size, and if the session is stored somewhere (database, file, memory cache... ), less time will be used in processing that information (usually serialization/deserialization and dealing with I/O operations).
For the guys who are impatient these are the results: NOTE: This information is just related to the test application used and its results cannot be generalized. If you want to see the underlying discussion please read the detailed document.


Comparing MyFaces and Mojarra in the graph, you can see MyFaces 2.1.7 has become the fastest by a wide margin (more than 40%!). Comparing Wicket 1.4.20 and 1.5.5 you can see 1.4.20 is faster. In this case, a better programming model in 1.5.5 has cost some speed. In Wicket, disk storage (default) and http session storage has different trade-offs.

In this case, MyFaces uses a lot less memory to do the same task and the memory used between Mojarra and Wicket 1.4.20 is more or less the same. Wicket disk storage requires more memory than session storage, because the pages need to be saved and restored from disk. Most memory is allocated by Wicket 1.5.5, but it is interesting that there is no significant difference between disk storage and session storage.

From a memory perspective, MyFaces is the winner but note that allocating more or less memory doesn't say much because part of this allocated memory could have a short life, but it is relevant if the web server has not a lot of memory. In a few words, the less bytes and objects allocated the better.


JSF average view size is very small compared to the user session size, imposing a reasonable overhead. In this case, MyFaces do the best job, keeping the state size very small, and the important part here is note that the state overhead for JSF grows very slowly. In Wicket case, since it stores the whole page into the state, it easily grow more quickly.

CONCLUSION


Definitively JSF 2.0 was a big move in the right direction. JSF session size overhead is significantly lower than Wicket. MyFaces Core 2.1.7 looks very well from a performance perspective against a web framework like Wicket. In the end, MyFaces provides the better trade-off between CPU usage and session size. The bet of Wicket on disk storage is good, but the JSF bet on partial state is even better. MyFaces also provides the lowest memory usage, which allows it to perform better in environments with limited CPU and memory.

Comparing Wicket 1.4 vs Wicket 1.5, it seems that the improvement in its programming model is taking a toll. In my opinion it is something completely reasonable. A good web framework needs to balance different aspects in order to keep evolving over the time. Including more assisting code usually means lower response times, but it could improve developer productivity.

This is not the end of the story. Web frameworks will keep improving and the hope is this information can be useful to find new ways to enhance them (community over code is the Apache way). Remember: performance is just one aspect that you have to consider when choosing a web framework; usually it is necessary to strike a balance between this and several other aspects.