Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Performance of resolving EL Value Expressions

I have a JSF2 application that renders a large table with complex content. Unfortunately, each request takes up to 6 seconds to process. Using simple debug output inside a phase listener, I could see that the performance loss distributes evenly over all phases that process the component tree. So I started up a profiler to see what's going on in detail and found out that over 300.000 ValueExpressions are evaluated during one simple request.

They resolve to really simple getters without any logic, so the problem is not executing the code behind these expressions but parsing the expression string and invoking the getter methods. This leads to a few questions:

1.) Is there any way to speed up the resolving of method expressions. Maybe a hidden "enable caching" flag or something.

2.) It seems most of the expressions are evaluated not inside the render response phase, where they are actually needed, but during the other phases. It seems unnecessary to resolve for example styleClass during any other phase than the render phase. Can I prevent this?

3.) Of course, minimizing the number of EL expressions in my facelets page should help getting more performance, but it seems that I cannot really do this: Many attributes (like the styleClass example mentioned above) are actually dependent on the table row, but can only be set on the column. So, having 10 columns, each expression is evaluated much too often. I've seen examples where the rowClasses attribute of the table is used to conditionally style the rows, but as the table is sortable, that won't work without rolling my own sorting mechanism. Is there a better way to implement this?

4.) One more simple question: Is there a way to cache variables in the component tree (just like ui:repeat provides access to the contents of a list and resolves the expression to get the list only once, but just for one variable)?

Thank you very much for all answers and hints!

EDIT:

After further investigation, I found out that for each rendered=#{someExpression}, the expression is evaluated 6 times per row just during the render response phase. I know that JSF may call my getters more than once, but I thought this would be because they can be called inside each phase. During rendering, that values shouldn't change, so I guess they could be cached.

Stepping through the code in the debugger, it looks like javax.faces.component.ComponentStateHelper (which appears in each of the stack traces leading to the evaluated method call) provides a map to do exactly this kind of caching. However, this doesn't seem to work as I expect and always re-evaluates the expression...

like image 625
FRotthowe Avatar asked Aug 05 '10 10:08

FRotthowe


People also ask

What are method value and expression?

The EL defines two kinds of expressions: value expressions and method expressions. Value expressions can either yield a value or set a value. Method expressions reference methods that can be invoked and can return a value.

What is EL expression in JSP?

Expression Language (EL) in JSP The Expression Language (EL) simplifies the accessibility of data stored in the Java Bean component, and other objects like request, session, application etc. There are many implicit objects, operators and reserve words in EL. It is the newly added feature in JSP technology version 2.0.

What is El in JSF?

Expression Language (EL), is a scripting language that's seen adoption within many Java frameworks, such as Spring with SpEL and JBoss with JBoss EL. In this article, we'll focus at the JSF's implementation of this scripting language – Unified EL.

Which is the correct syntax to use method expression in a JSF page?

Because a method can be invoked during different phases of the lifecycle, method expressions must always use the deferred evaluation syntax. Like lvalue expressions, method expressions can use the . and the [] operators.


2 Answers

1.) Is there any way to speed up the resolving of method expressions. Maybe a hidden "enable caching" flag or something.

No one comes to mind.

2.) It seems most of the expressions are evaluated not inside the render response phase, where they are actually needed, but during the other phases. It seems unnecessary to resolve for example styleClass during any other phase than the render phase. Can I prevent this?

This should as far as I know not happen. The only ones which could/should be resolved before render response are rendered, required, disabled, readonly and value.

3.) Of course, minimizing the number of EL expressions in my facelets page should help getting more performance, but it seems that I cannot really do this: Many attributes (like the styleClass example mentioned above) are actually dependent on the table row, but can only be set on the column. So, having 10 columns, each expression is evaluated much too often. I've seen examples where the rowClasses attribute of the table is used to conditionally style the rows, but as the table is sortable, that won't work without rolling my own sorting mechanism. Is there a better way to implement this?

You could hand over the styling work to a smart piece/combination of JS/CSS.

4.) One more simple question: Is there a way to cache variables in the component tree (just like ui:repeat provides access to the contents of a list and resolves the expression to get the list only once, but just for one variable)?

Use JSTL <c:set>. I am not sure how that would affect after all, but you're then basically only moving the problem to somewhere else. A #{variableName} would still have a cost of locating it in any of the scopes. You can also consider to name the scope explicitly when accessing the variable. E.g. #{sessionScope.beanname} which should skip unnecessarily scanning in page and request scopes.

like image 75
BalusC Avatar answered Oct 13 '22 09:10

BalusC


I know this one is kinda old but I want to add that this issue has been solved by the MyFaces implementation. It is documented in their Wiki: https://cwiki.apache.org/confluence/display/MYFACES/Cache+EL+Expressions

like image 22
tasel Avatar answered Oct 13 '22 09:10

tasel