My JSF Books/Videos My JSF Tutorials OmniFaces/JSF PPTs
JSF 2.3 Tutorial
JSF Caching Tutorial
JSF Navigation Tutorial
JSF Scopes Tutorial
JSF Page Author Beginner's Guide
OmniFaces 2.3 Tutorial Examples
OmniFaces 2.2 Tutorial Examples
JSF Events Tutorial
OmniFaces Callbacks Usages
JSF State Tutorial
JSF and Design Patterns
JSF 2.3 New Features (2.3-m04)
Introduction to OmniFaces
25+ Reasons to use OmniFaces in JSF
OmniFaces Validators
OmniFaces Converters
JSF Design Patterns
Mastering OmniFaces
Reusable and less-verbose JSF code

My JSF Resources ...

Java EE Guardian
Member of JCG Program
Member MVB DZone
Blog curated on ZEEF
OmniFaces is an utility library for JSF, including PrimeFaces, RichFaces, ICEfaces ...

[OmniFaces Utilities] - Find the right JSF OmniFaces 2 utilities methods/functions

Search on blog

Petition by Java EE Guardians


duminică, 28 decembrie 2014

Test OmniFaces Cache for Render Response Phase

As a JSF developer, you know that the Render Response phase (the sixth phase) is one of the most time-expensive of all JSF phases, next to the Restore View phase (first phase). Well, OmniFaces provides a component, named Cache which is an server-side caching mechanism. Basically, it allows us to cache a piece of markup produced by the JSF renderers. While the OmniFaces showcase provides clear examples of how to use the Cache (<o:cache>) component, this post tries to test how useful is to cache markup on server-side. We can easily intuit that the <o:cache> should speed up the Render Response phase, but that will have an impact over other aspects also, like memory usage.
So, we tried to accomplish this test for a JSF data table, with variable number of records (rows). The table has nine columns, and it looks like this:
<h:dataTable value="#{}" var="t" border="1">
   <f:facet name="header">Ranking</f:facet>                   
   <h:outputText value="#{t.ranking}" style="color:red;"/>                             
   <f:facet name="header">Name</f:facet>                       
   <h:outputText value="#{t.player}">
    <f:converter converterId="lowerCaseConverter"/>
   <f:facet name="header">Age</f:facet>                       
   <h:outputText value="#{t.age}">
    <f:converter converterId="ageConverter"/>
   <f:facet name="header">Birthplace</f:facet>                      
   <h:outputText value="#{t.birthplace}">
    <f:converter converterId="lowerCaseConverter"/>
   <f:facet name="header">Residence</f:facet>                      
   <h:outputText value="#{t.residence}">
    <f:converter converterId="lowerCaseConverter"/>
   <f:facet name="header">Height</f:facet>
   <h:outputText value="#{t.height}">
    <f:converter converterId="heighConverter"/>
   <f:facet name="header">Weight</f:facet>
   <h:outputText value="#{t.weight}">
    <f:converter converterId="weightConverter"/>
   <f:facet name="header">Coach</f:facet>                        
   <h:outputText value="#{}">
    <f:converter converterId="lowerCaseConverter"/>
   <f:facet name="header">Born</f:facet>
   <h:outputText value="#{t.born}">               
    <f:convertDateTime pattern="dd.MM.yyyy" />

This table is useful because it will produce a lot of markup and we can juggle with the number of records (rows) which means that we can easily control the amount of markup. Moreover, this is a fix table, so is a good opportunity to cache its content instead of rendering it at each postback.
We've performed 5 tests without caching and 5 with caching by varying the number of records (rows) at each test, as follows: 500, 1000, 2000, 5000 and 10000 records (rows). For each test, we have performed 5 consecutives postbacks requests (only one request executed at a time, but all 5 executed in the same minute). For each JSF phase, the initial request and the averages times of postbacks were plotted with respect to the JSF phases (the measurements were made using a JSF phase listener and the System.nanoTime()). The initial request is plotted in the left, and the postbacks in the right.

In the chart below, you can see the results for 500 records (rows):

Next, for 1000 records (rows):

Next, for 2000 records (rows):

Next, for 5000 records (rows):

Now, for 10000 records (rows):

Well, the results are pretty clear. The OmniFaces caching was very useful and has a significant impact on server response time. Is true, and normal, that the initial request takes longer when cache is used (since is a extra task in the rendering phase), but the time lost here is won on postbacks.
 The Application Server GlassFish 4 was used, and the AppDynamics revealed the following charts (the very, very small differences that appears between the above values in miliseconds and the below ones are caused by the fact the above values were obtained via System.nanoTime() and the below ones are obtained via AppDynamics, which is a powerful Application Performance Management tool):

·         first, we have the calls per minute - the points at scale 1 represents the initial requests, while the points at scale 5, represents the postbacks for each run, and there are 5 different runs. Between the initial request and the 5 postbacks, there is a minute without requests - this is happening for each run. As you can see, the charts are the "same", only the times of running differs, which is normal. This chart is a prove that the tests were done under the same conditions.

·         next chart shows the average response time for each run. Is obvious that when cache is not used, all averages are bigger than when cached is used.

·         in order to perceive better, let's check the chart that contains the postbacks times sum. Notice that at 10000 records (rows), the cache will speed up the postbacks times sum with more than 3 seconds.

·         below you can see the distribution of the slowest and the fastest responses during 5 postbacks

·         and, the slowest and fastest requests in respect with calls per minute

·         the next chart reveals the total average response time over the whole 5 runs (196 ms faster with cache)

·         is time to see how the memory was distributed over these 5 runs. So, notice that in case of cache the difference between the average utilization of heap memory is only 1%!

For fine-grained conclusion we also may check:

·         the garbage collector usage

·         the memory pools

The test was performed under the following items:

Notice that this test doesn't involve the useBuffer="true" !!!

Niciun comentariu :

Trimiteți un comentariu


Postări populare

Follow by Email

Visitors Starting 4 September 2015

Locations of Site Visitors