Environment:
If you would like to use a JavaEE application server, i would go with TomEE.
It's the fastest and smallest application server available and already comes with Apache MyFaces as JSF implementation and Apache OpenWebBeans as CDI implementation.
There are already really good benchmarks available why we should choose MyFaces over Mojarra and OpenWebBeans over Weld:
Understanding JSF 2.0 Performance – Part 1
Understanding JSF 2.0 Performance – Part 2
Understanding JSF 2.0 Performance – Part 3
CDI Performance
So if you just use a plain servlet container like Tomcat or Jetty, i would also use MyFaces and OpenWebBeans.
In the past it was also a good performance boost if you use JUEL over Tomcat's EL implementation - sadly JUEL doesn't implement EL 3.0.
Configuration:
- Common settings:
<context-param> <param-name>javax.faces.PROJECT_STAGE</param-name> <param-value>Production</param-value> </context-param> <context-param> <param-name>javax.faces.FACELETS_REFRESH_PERIOD</param-name> <param-value>-1</param-value> </context-param> <context-param> <param-name>javax.faces.STATE_SAVING_METHOD</param-name> <param-value>server</param-value> </context-param>
<context-param> <param-name>org.apache.myfaces.CACHE_EL_EXPRESSIONS</param-name> <param-value>alwaysRecompile</param-value> </context-param>
<context-param> <param-name>org.apache.myfaces.SUPPORT_JSP_AND_FACES_EL</param-name> <param-value>false</param-value> </context-param> <!-- NOTE: the ExpressionFactory might differ e.g. on Glassfish or Wildfly. This parameter is optional since MyFaces 2.3.3. --> <context-param> <param-name>org.apache.myfaces.EXPRESSION_FACTORY</param-name> <param-value>org.apache.el.ExpressionFactoryImpl</param-value> </context-param>
<context-param> <param-name>org.apache.myfaces.SUPPORT_MANAGED_BEANS</param-name> <param-value>false</param-value> </context-param>
<context-param> <param-name>org.apache.myfaces.NUMBER_OF_VIEWS_IN_SESSION</param-name> <param-value>15</param-value> </context-param> <context-param> <param-name>org.apache.myfaces.NUMBER_OF_SEQUENTIAL_VIEWS_IN_SESSION</param-name> <param-value>3</param-value> </context-param>
<context-param> <param-name>org.apache.myfaces.COMPRESS_STATE_IN_SESSION</param-name> <param-value>false</param-value> </context-param>
<context-param> <param-name>primefaces.SUBMIT</param-name> <param-value>partial</param-value> </context-param>
<context-param> <param-name>primefaces.MOVE_SCRIPTS_TO_BOTTOM</param-name> <param-value>true</param-value> </context-param>
<context-param> <param-name>org.apache.myfaces.CHECK_ID_PRODUCTION_MODE</param-name> <param-value>false</param-value> </context-param> <context-param> <param-name>org.apache.myfaces.EARLY_FLUSH_ENABLED</param-name> <param-value>true</param-value> </context-param>
Patterns:
- Correctly define update/render and process/execute! Often this is a huge improvement as many times the whole form is updated instead only a small part. But i also prefer maintainability over performance here.
- If you don't use ViewScoped beans, it's a good but small improvement to mark the view as stateless via transient=true.
- Try using HTML over JSF tags.
- Especially avoid using h:outputText if you don't need the escaping. Just use EL expressions inside your xhtml template.
- The same applies for some other components like p:outputPanel. Just use a plain div. If you need to make it updateable, you can still use "passtrough elements" (<div jsf:id="...">...</div>)
- Never put logic in getters because they can be called multiple times - especially for the rendered attribute!
- Avoid logic (like inline if-statements) in EL expression! It's better to move those logic into the bean. It's faster and often easier to read and maintain.
- Prefer AJAX over a full postback!
- If you have many p:outputLabel's on the page and you know that the input field is required or not, it's a good performance improvemet to set the input to required=true or the outputLabel to indicateRequired=true|false. The default value for indicateRequired since 6.2 is auto, which tries to lookup BeanValidation constrains to check if @NotNull|@NotEmpty|@NotBlank are defined.
- Cache data, which is required multiple times in the same view, in @RequestScoped beans.
- Avoid missusing @SessionScoped, @ViewScoped and other long living scopes if not really required.
- Try to put only small amount of data in such long living beans. Sometimes a small flag or id of an entity is enough information. Often people put many entities in such long living beans. One of my patterns is to split beans into *Controllers (@RequestScoped) and *StateHolders (@ViewScoped, @ViewAccessScoped). *StateHolders are just data containers.
Hi, Thanks for the tips. Some of them are targeted for myfaces 2.3.0, which is still in beta. Do you think is safe to use it as is or a release will happen soon? (just wanted to know)
ReplyDeleteThanks!
I would not use the beta, we already fixed many bugs since the beta release. I think it's the best to wait 1-2 months.
ReplyDeleteThanks for this important collected tips for better JSF performance.
ReplyDeleteCan you advice or recommend how to measure the performance of JSF pages to compare our changes before and after to be more objective
p:lifecycle for a single page - however the difference will not be very big. I would use jmeter ;)
DeleteI would be very curious what the current advantage is of view pooling for a seriously ajax intensive appplication. E.g. a complex form where each input is submitted, processed, validated and maybe some other fields are updated. For something I'm working on, this (in addition to some other advantages) would be the most relevant reason to switch from Mojarra 2.3.x to MyFaces 2.3.x. Does PF work 'flawlessly' with viewpooling?
ReplyDeleteI would suggest to take a look at the linked benchmark - the biggest benefit comes from switching from mojarra to myfaces without viewpooling or stateless: http://content.jsfcentral.com/documents/35702/69490/Fog304.PNG/1784d51a-e948-4830-b46e-d3c4c19b95cb?t=1371263288000
DeleteAs you can see, viewpooling just improves the already gained perf: http://content.jsfcentral.com/documents/35702/69490/Fig306.PNG/9459636b-3a79-4820-825a-1d61b3eaf11c?t=1371263318000
ViewPooling has only one disadvantage: PostAddToViewEvent doesn't work as before. I fixed an incompatibility with p:autoUpdate for 6.2. Everything is working now fine in my applications - also already in production.
JFYI: ViewPooling is already available in 2.2. Currently there are only 2-3 tickets left for doing a MyFaces 2.3.0 release. I would be great if could give it a try before ;)
the benchmarks are a bit old, with version 2.2 or 2.3 things are not very different?
DeleteI dont think so. In MyFaces we always improve performance in each release. So it personally think the difference is the same or MyFaces even faster. But you can just run it again ;)
Delete(previous 'unknown' post was made by 'kukeltje' ;-)
ReplyDeleteWhat do you think is a good value for compressionMinSize in Tomcat?
ReplyDeleteThank you for the information, good content.
ReplyDeleteSearching for Software Development Company? 3sstudio is Considered as the most well-established Software Development Company in Delhi offers you an entire range of Development services as far as ERP & CRM Development, with more than 1000+ satisfied clients.
This comment has been removed by the author.
ReplyDeleteReally helpful one. Thanks for sharing this nice one.
ReplyDeleteMobile App Development Services in Chennai
It is really informative. Thanks for sharing this wonderful blog with us.
ReplyDeletebulk sms marketing chennai
bulk sms service chennai
promotional sms chennai
sms marketing chennai
sms service provider in chennai
bulk whatsapp service provider in chennai
bulk sms marketing in chennai
bulk sms price in chennai
bulk sms provider chennai
bulk sms service provider in chennai
chennai bulk sms
best bulk sms service provider in chennai
bulksms in Chennai