[ 
https://jira.jboss.org/jira/browse/RF-8197?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Jan Ziegler updated RF-8197:
----------------------------

    Description: 
I just realized some possible "lifecycle processing overhead" when doing ajax 
actions: 
In render response phase each ajax component is checked for rendering by the 
method AjaxChildrenRenderer.encodeAjaxComponent(). That - what I could see -  
is the case when:
1) the component´s rendered-attribute is true
2) the component is ajaxRendered 
3) the componentId is defined in the reRenderId-List

This also reflects the order of checking, so the first thing to be done is 
check if the component´s rendered-attribute is true. But this might also lead 
to additional lifecycle processings when 
 rendered-conditions are bound to managed beans by el expressions. To evaluate 
the rendered condition, request scoped managed beans must be created. to my 
opion this is suboptimal, like in my case the managed bean performs some (time 
intensive?) actions in its constructor or the rendered conditions relies on a 
list which must be fetched from the database - and this also happens even if 
the componentId is not in den reRenderId-List. 

So why not first evaluate if the componentId is in the reRenderId-List or the 
component is ajaxRendered and then (if one of this conditions is true) 
additionally check the rendered-condition?

This might be accomplished with a small change 
AjaxChildrenRenderer.encodeAjaxComponent():

{code}
public void encodeAjaxComponent(FacesContext context,
                        UIComponent component, String currentPath, Set<String> 
ids,
                        Set<String> renderedAreas) throws IOException {
                if (component.isRendered()) { // skip not-rendered components.
                        boolean found = false;
                        boolean limitToList = 
AjaxContext.getCurrentInstance(context).isLimitToList();
                        String elementId = component.getId();
                        String absoluteId = currentPath + elementId;
                        if (!ids.isEmpty()) {
                                // list for rendering may contains absolute id 
( best ),
                                // component Id or client ID
                                // String clientId = 
element.getClientId(context);
                                if (ids.contains(absoluteId) || 
ids.contains(elementId)) {
                                        if (log.isDebugEnabled()) {
                                                log.debug(Messages.getMessage(
                                                                
Messages.RENDER_AJAX_AREA_INFO, absoluteId));
                                        }
                                        // renderChild(context, element);
                                        found = true;
                                }
                        }
                        // 
                        if (!found && limitToList
                                        && component instanceof NamingContainer
                                        && noIdUnderPath(absoluteId
                                                        + 
NamingContainer.SEPARATOR_CHAR, ids)) {
                                return;
                        }
                        if (!found && !limitToList && component instanceof 
AjaxOutput) {
                                if (((AjaxOutput) component).isAjaxRendered()) {
                                        // renderChild(context, element);
                                        found = true;
                                }

                        }

                        if (!found) {
                                if (component instanceof AjaxChildrenEncoder) {
                                        ((AjaxChildrenEncoder) 
component).encodeAjaxChild(context,
                                                        currentPath, ids, 
renderedAreas);
                                } else {
                                        // Special case - for control 
components, not produced
                                        // html code - such as message bundles 
loaders,
                                        // MyFaces aliases etc. we call 
encodeBegin/end methods
                                        // even if components not in rendered 
areas.
                                        boolean special = 
isSpecialElement(context, component);
                                        if (special) {
                                                component.encodeBegin(context);
                                        }
                                        encodeAjaxChildren(context, component, 
currentPath, ids,
                                                        renderedAreas);
                                        if (special) {
                                                component.encodeEnd(context);
                                        }

                                }
                        } else {
                                
renderedAreas.add(component.getClientId(context));
                                renderChild(context, component);
                        }
                }
        }
{code}

Patched version (the isRendered()-condition is moved the the last else-Block 
before renderChild() is called and the component will be rendered):

public void encodeAjaxComponent(FacesContext context,
                        UIComponent component, String currentPath, Set<String> 
ids,
                        Set<String> renderedAreas) throws IOException {
                boolean found = false;
                boolean limitToList = 
AjaxContext.getCurrentInstance(context).isLimitToList();
                String elementId = component.getId();
                String absoluteId = currentPath + elementId;
                if (!ids.isEmpty()) {
                        // list for rendering may contains absolute id ( best ),
                        // component Id or client ID
                        // String clientId = element.getClientId(context);
                        if (ids.contains(absoluteId) || 
ids.contains(elementId)) {
                                if (log.isDebugEnabled()) {
                                        log.debug(Messages.getMessage(
                                                        
Messages.RENDER_AJAX_AREA_INFO, absoluteId));
                                }
                                // renderChild(context, element);
                                found = true;
                        }
                }
                // 
                if (!found && limitToList
                                && component instanceof NamingContainer
                                && noIdUnderPath(absoluteId
                                                + 
NamingContainer.SEPARATOR_CHAR, ids)) {
                        return;
                }
                if (!found && !limitToList && component instanceof AjaxOutput) {
                        if (((AjaxOutput) component).isAjaxRendered()) {
                                // renderChild(context, element);
                                found = true;
                        }

                }

                if (!found) {
                        if (component instanceof AjaxChildrenEncoder) {
                                ((AjaxChildrenEncoder) 
component).encodeAjaxChild(context,
                                                currentPath, ids, 
renderedAreas);
                        } else {
                                // Special case - for control components, not 
produced
                                // html code - such as message bundles loaders,
                                // MyFaces aliases etc. we call encodeBegin/end 
methods
                                // even if components not in rendered areas.
                                boolean special = isSpecialElement(context, 
component);
                                if (special) {
                                        component.encodeBegin(context);
                                }
                                encodeAjaxChildren(context, component, 
currentPath, ids,
                                                renderedAreas);
                                if (special) {
                                        component.encodeEnd(context);
                                }

                        }
                } else if (component.isRendered()) { // skip not-rendered 
components.
                        renderedAreas.add(component.getClientId(context));
                        renderChild(context, component);
                }
        }
{code}

  was:
I just realized some possible "lifecycle processing overhead" when doing ajax 
actions: 
In render response phase each ajax component is checked for rendering by the 
method AjaxChildrenRenderer.encodeAjaxComponent(). That - what I could see -  
is the case when:
1) the component´s rendered-attribute is true
2) the component is ajaxRendered 
3) the componentId is defined in the reRenderId-List

This also reflects the order of checking, so the first thing to be done is 
check if the component´s rendered-attribute is true. But this might also lead 
to additional lifecycle processings when 
 rendered-conditions are bound to managed beans by el expressions. To evaluate 
the rendered condition, request scoped managed beans must be created. to my 
opion this is suboptimal, like in my case the managed bean performs some (time 
intensive?) actions in its constructor or the rendered conditions relies on a 
list which must be fetched from the database - and this also happens even if 
the componentId is not in den reRenderId-List. 

So why not first evaluate if the componentId is in the reRenderId-List or the 
component is ajaxRendered and then (if one of this conditions is true) 
additionally check the rendered-condition?

This might be accomplished with a small change 
AjaxChildrenRenderer.encodeAjaxComponent():

{code}
public void encodeAjaxComponent(FacesContext context,
                        UIComponent component, String currentPath, Set<String> 
ids,
                        Set<String> renderedAreas) throws IOException {
                if (component.isRendered()) { // skip not-rendered components.
                        boolean found = false;
                        boolean limitToList = 
AjaxContext.getCurrentInstance(context).isLimitToList();
                        String elementId = component.getId();
                        String absoluteId = currentPath + elementId;
                        if (!ids.isEmpty()) {
                                // list for rendering may contains absolute id 
( best ),
                                // component Id or client ID
                                // String clientId = 
element.getClientId(context);
                                if (ids.contains(absoluteId) || 
ids.contains(elementId)) {
                                        if (log.isDebugEnabled()) {
                                                log.debug(Messages.getMessage(
                                                                
Messages.RENDER_AJAX_AREA_INFO, absoluteId));
                                        }
                                        // renderChild(context, element);
                                        found = true;
                                }
                        }
                        // 
                        if (!found && limitToList
                                        && component instanceof NamingContainer
                                        && noIdUnderPath(absoluteId
                                                        + 
NamingContainer.SEPARATOR_CHAR, ids)) {
                                return;
                        }
                        if (!found && !limitToList && component instanceof 
AjaxOutput) {
                                if (((AjaxOutput) component).isAjaxRendered()) {
                                        // renderChild(context, element);
                                        found = true;
                                }

                        }

                        if (!found) {
                                if (component instanceof AjaxChildrenEncoder) {
                                        ((AjaxChildrenEncoder) 
component).encodeAjaxChild(context,
                                                        currentPath, ids, 
renderedAreas);
                                } else {
                                        // Special case - for control 
components, not produced
                                        // html code - such as message bundles 
loaders,
                                        // MyFaces aliases etc. we call 
encodeBegin/end methods
                                        // even if components not in rendered 
areas.
                                        boolean special = 
isSpecialElement(context, component);
                                        if (special) {
                                                component.encodeBegin(context);
                                        }
                                        encodeAjaxChildren(context, component, 
currentPath, ids,
                                                        renderedAreas);
                                        if (special) {
                                                component.encodeEnd(context);
                                        }

                                }
                        } else {
                                
renderedAreas.add(component.getClientId(context));
                                renderChild(context, component);
                        }
                }
        }
{code}

Patched version (the isRendered()-condition is moved the the last else-Block 
before the component will be rendered):

public void encodeAjaxComponent(FacesContext context,
                        UIComponent component, String currentPath, Set<String> 
ids,
                        Set<String> renderedAreas) throws IOException {
                boolean found = false;
                boolean limitToList = 
AjaxContext.getCurrentInstance(context).isLimitToList();
                String elementId = component.getId();
                String absoluteId = currentPath + elementId;
                if (!ids.isEmpty()) {
                        // list for rendering may contains absolute id ( best ),
                        // component Id or client ID
                        // String clientId = element.getClientId(context);
                        if (ids.contains(absoluteId) || 
ids.contains(elementId)) {
                                if (log.isDebugEnabled()) {
                                        log.debug(Messages.getMessage(
                                                        
Messages.RENDER_AJAX_AREA_INFO, absoluteId));
                                }
                                // renderChild(context, element);
                                found = true;
                        }
                }
                // 
                if (!found && limitToList
                                && component instanceof NamingContainer
                                && noIdUnderPath(absoluteId
                                                + 
NamingContainer.SEPARATOR_CHAR, ids)) {
                        return;
                }
                if (!found && !limitToList && component instanceof AjaxOutput) {
                        if (((AjaxOutput) component).isAjaxRendered()) {
                                // renderChild(context, element);
                                found = true;
                        }

                }

                if (!found) {
                        if (component instanceof AjaxChildrenEncoder) {
                                ((AjaxChildrenEncoder) 
component).encodeAjaxChild(context,
                                                currentPath, ids, 
renderedAreas);
                        } else {
                                // Special case - for control components, not 
produced
                                // html code - such as message bundles loaders,
                                // MyFaces aliases etc. we call encodeBegin/end 
methods
                                // even if components not in rendered areas.
                                boolean special = isSpecialElement(context, 
component);
                                if (special) {
                                        component.encodeBegin(context);
                                }
                                encodeAjaxChildren(context, component, 
currentPath, ids,
                                                renderedAreas);
                                if (special) {
                                        component.encodeEnd(context);
                                }

                        }
                } else if (component.isRendered()) { // skip not-rendered 
components.
                        renderedAreas.add(component.getClientId(context));
                        renderChild(context, component);
                }
        }
{code}



> Optimize AjaxChildrenRenderer render component check algorithm
> --------------------------------------------------------------
>
>                 Key: RF-8197
>                 URL: https://jira.jboss.org/jira/browse/RF-8197
>             Project: RichFaces
>          Issue Type: Patch
>      Security Level: Public(Everyone can see) 
>    Affects Versions: 3.3.2.SR1
>         Environment: Myfaces 1.2.8, Facelets 1.1.15, Tomcat 6.0.20
>            Reporter: Jan Ziegler
>
> I just realized some possible "lifecycle processing overhead" when doing ajax 
> actions: 
> In render response phase each ajax component is checked for rendering by the 
> method AjaxChildrenRenderer.encodeAjaxComponent(). That - what I could see -  
> is the case when:
> 1) the component´s rendered-attribute is true
> 2) the component is ajaxRendered 
> 3) the componentId is defined in the reRenderId-List
> This also reflects the order of checking, so the first thing to be done is 
> check if the component´s rendered-attribute is true. But this might also lead 
> to additional lifecycle processings when 
>  rendered-conditions are bound to managed beans by el expressions. To 
> evaluate the rendered condition, request scoped managed beans must be 
> created. to my opion this is suboptimal, like in my case the managed bean 
> performs some (time intensive?) actions in its constructor or the rendered 
> conditions relies on a list which must be fetched from the database - and 
> this also happens even if the componentId is not in den reRenderId-List. 
> So why not first evaluate if the componentId is in the reRenderId-List or the 
> component is ajaxRendered and then (if one of this conditions is true) 
> additionally check the rendered-condition?
> This might be accomplished with a small change 
> AjaxChildrenRenderer.encodeAjaxComponent():
> {code}
> public void encodeAjaxComponent(FacesContext context,
>                       UIComponent component, String currentPath, Set<String> 
> ids,
>                       Set<String> renderedAreas) throws IOException {
>               if (component.isRendered()) { // skip not-rendered components.
>                       boolean found = false;
>                       boolean limitToList = 
> AjaxContext.getCurrentInstance(context).isLimitToList();
>                       String elementId = component.getId();
>                       String absoluteId = currentPath + elementId;
>                       if (!ids.isEmpty()) {
>                               // list for rendering may contains absolute id 
> ( best ),
>                               // component Id or client ID
>                               // String clientId = 
> element.getClientId(context);
>                               if (ids.contains(absoluteId) || 
> ids.contains(elementId)) {
>                                       if (log.isDebugEnabled()) {
>                                               log.debug(Messages.getMessage(
>                                                               
> Messages.RENDER_AJAX_AREA_INFO, absoluteId));
>                                       }
>                                       // renderChild(context, element);
>                                       found = true;
>                               }
>                       }
>                       // 
>                       if (!found && limitToList
>                                       && component instanceof NamingContainer
>                                       && noIdUnderPath(absoluteId
>                                                       + 
> NamingContainer.SEPARATOR_CHAR, ids)) {
>                               return;
>                       }
>                       if (!found && !limitToList && component instanceof 
> AjaxOutput) {
>                               if (((AjaxOutput) component).isAjaxRendered()) {
>                                       // renderChild(context, element);
>                                       found = true;
>                               }
>                       }
>                       if (!found) {
>                               if (component instanceof AjaxChildrenEncoder) {
>                                       ((AjaxChildrenEncoder) 
> component).encodeAjaxChild(context,
>                                                       currentPath, ids, 
> renderedAreas);
>                               } else {
>                                       // Special case - for control 
> components, not produced
>                                       // html code - such as message bundles 
> loaders,
>                                       // MyFaces aliases etc. we call 
> encodeBegin/end methods
>                                       // even if components not in rendered 
> areas.
>                                       boolean special = 
> isSpecialElement(context, component);
>                                       if (special) {
>                                               component.encodeBegin(context);
>                                       }
>                                       encodeAjaxChildren(context, component, 
> currentPath, ids,
>                                                       renderedAreas);
>                                       if (special) {
>                                               component.encodeEnd(context);
>                                       }
>                               }
>                       } else {
>                               
> renderedAreas.add(component.getClientId(context));
>                               renderChild(context, component);
>                       }
>               }
>       }
> {code}
> Patched version (the isRendered()-condition is moved the the last else-Block 
> before renderChild() is called and the component will be rendered):
> public void encodeAjaxComponent(FacesContext context,
>                       UIComponent component, String currentPath, Set<String> 
> ids,
>                       Set<String> renderedAreas) throws IOException {
>               boolean found = false;
>               boolean limitToList = 
> AjaxContext.getCurrentInstance(context).isLimitToList();
>               String elementId = component.getId();
>               String absoluteId = currentPath + elementId;
>               if (!ids.isEmpty()) {
>                       // list for rendering may contains absolute id ( best ),
>                       // component Id or client ID
>                       // String clientId = element.getClientId(context);
>                       if (ids.contains(absoluteId) || 
> ids.contains(elementId)) {
>                               if (log.isDebugEnabled()) {
>                                       log.debug(Messages.getMessage(
>                                                       
> Messages.RENDER_AJAX_AREA_INFO, absoluteId));
>                               }
>                               // renderChild(context, element);
>                               found = true;
>                       }
>               }
>               // 
>               if (!found && limitToList
>                               && component instanceof NamingContainer
>                               && noIdUnderPath(absoluteId
>                                               + 
> NamingContainer.SEPARATOR_CHAR, ids)) {
>                       return;
>               }
>               if (!found && !limitToList && component instanceof AjaxOutput) {
>                       if (((AjaxOutput) component).isAjaxRendered()) {
>                               // renderChild(context, element);
>                               found = true;
>                       }
>               }
>               if (!found) {
>                       if (component instanceof AjaxChildrenEncoder) {
>                               ((AjaxChildrenEncoder) 
> component).encodeAjaxChild(context,
>                                               currentPath, ids, 
> renderedAreas);
>                       } else {
>                               // Special case - for control components, not 
> produced
>                               // html code - such as message bundles loaders,
>                               // MyFaces aliases etc. we call encodeBegin/end 
> methods
>                               // even if components not in rendered areas.
>                               boolean special = isSpecialElement(context, 
> component);
>                               if (special) {
>                                       component.encodeBegin(context);
>                               }
>                               encodeAjaxChildren(context, component, 
> currentPath, ids,
>                                               renderedAreas);
>                               if (special) {
>                                       component.encodeEnd(context);
>                               }
>                       }
>               } else if (component.isRendered()) { // skip not-rendered 
> components.
>                       renderedAreas.add(component.getClientId(context));
>                       renderChild(context, component);
>               }
>       }
> {code}

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: 
https://jira.jboss.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

       

_______________________________________________
richfaces-issues mailing list
[email protected]
https://lists.jboss.org/mailman/listinfo/richfaces-issues

Reply via email to