myfaces-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Simon Kitching <simon.kitch...@rhe.co.nz>
Subject Re: Multiple calls on isRendered - Performance issue
Date Tue, 08 May 2007 20:44:25 GMT
Andrew, are you just stating what currently happens or are you saying 
that there is a *reason* for evaluating "rendered" in encodeBegin, 
encodeChildren and encodeEnd?

I can't initially see any reason why it would need to be evaluated more 
than once.

UIComponentBase does indeed call isRendered in encodeBegin, 
encodeChildren and encodeEnd. It also implements isRendered as an 
evaluation of the EL expression (myfaces 1.1.3 implementation).

But As Wesley asks, why would it ever make sense for rendered to be true 
in encodeBegin, but false in encodeEnd? I cannot see any way that would 
be useful, so why not just compute it once then cache it somewhere for 
the rest of that render cycle (eg in a "transient" member of the 
component)? This would be a significant performance boost..

Wesley, your proposed modification which stores the rendered state into 
_rendered is not good because setting _rendered will permanently 
override the rendered EL expression, not just for the current render 
cycle but for the lifetime of that component. What is needed is to 
figure out when the first call to isRendered is done *during the render 
cycle* and then cache that until rendering finishes. Note that 
isRendered is also called during postback processing, and it's perfectly 
reasonable to change this value between postback and render so caching 
really should only be done between encodeBegin() and encodeEnd(). So 
implementing this optimisation is a little tricky - but not impossible 
I'm sure.

Regards,

Simon

Andrew Robinson wrote:
> At the very least rendered is called during encodeBegin,
> encodeChildren, and encodeEnd.
> 
> On 5/8/07, Wesley Hales <wesleyhales@gmail.com> wrote:
>> Hello - Why do we continually call isRendered after encodeBegin()? 
>> Once the
>> begin tag is written out, it shouldn't matter what the body and end 
>> rendered
>> states are.
>>
>> Facelets 1.1.11
>>  Myfaces 1.1.5 & 1.2
>>
>> So if I have  <t:div rendered="#{MyBean.alerts > 0}"...
>> The #{MyBean.alerts method is called 5 times! and it is like this for 
>> every
>> EL eval on the page. I do know that EL can only bind to the 
>> FaceletsContext
>> and no other scopes... So are there any other options than what I have
>> listed below?
>>
>> 1. Tried to modify MyFaces src in UIComponentBase:
>> public boolean isRendered()
>>      {
>>            if(_rendered == null){
>>
>>            // our modification! Only compute the rendered value once, and
>> cache for the rest of the lifecycle.
>>            Boolean rend = getExpressionValue("rendered", _rendered,
>> DEFAULT_RENDERED);
>>            _rendered = rend.booleanValue();
>>            }
>>          return _rendered;
>>      }
>> This didn't work :( - Something happend to A4J and we had no ideas 
>> what the
>> implication would be on all components.
>>
>> 2. Tried using Facelets <ui:param and <c:set to store the EL in a page
>> scoped variable, then have the variable evaluated in the rendered 
>> attribute.
>> This didn't work either because it is on FacesContext.
>>
>> So this may just be me not fully understanding  what JSF does behind the
>> scenes of component rendering, or some people say that  the spec is 
>> screwed
>> up when it comes to this. I'm sure some of the pros can help me out 
>> here :).
>>
>> Thx,
>> Wesley Hales


Mime
View raw message