You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@myfaces.apache.org by "Martin Kočí (JIRA)" <de...@myfaces.apache.org> on 2011/05/13 21:13:47 UTC

[jira] [Created] (MYFACES-3144) [PERF] Cache renderer in UIComponentBase

[PERF] Cache renderer in UIComponentBase
----------------------------------------

                 Key: MYFACES-3144
                 URL: https://issues.apache.org/jira/browse/MYFACES-3144
             Project: MyFaces Core
          Issue Type: New Feature
          Components: General
    Affects Versions: 2.1.0-SNAPSHOT
         Environment: myfaces core trunk
            Reporter: Martin Kočí
            Assignee: Martin Kočí


UIComponentBase uses getRenderer(): Renderer in five methods:
1) decode
2) encodeBegin
3) encodeChildren
4) encodeEnd
50 getClientId

getting the renderer is not cheap if you have thousands component in view. 

Cache renderer instance in UIComponentBase (Trinidad UIXComponentBase does it already)



--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira

[jira] [Commented] (MYFACES-3144) [PERF] Cache renderer in UIComponentBase

Posted by "Leonardo Uribe (JIRA)" <de...@myfaces.apache.org>.
    [ https://issues.apache.org/jira/browse/MYFACES-3144?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13051172#comment-13051172 ] 

Leonardo Uribe commented on MYFACES-3144:
-----------------------------------------

I think there is one alternative to do this. To retrieve a renderer we need three params:

1. renderKitId
2. family
3. rendererType

family and rendererType does not change, but renderKitId could change. So, why don't save on a transient field the latest renderKitId used to derive the renderer? Then, when getRenderer() is called we just compare that field against the current one and if are equals we can return the cached instance, otherwise recalculate it. 

But anyway it is questionable if we can gain something with this strategy, because in practice we replace a simple comparison between two strings + an additional field on every component against two lookups over a map. At first view, let the code "as is" looks good, so only if we can gain something it is worth to do it.

> [PERF] Cache renderer in UIComponentBase
> ----------------------------------------
>
>                 Key: MYFACES-3144
>                 URL: https://issues.apache.org/jira/browse/MYFACES-3144
>             Project: MyFaces Core
>          Issue Type: New Feature
>          Components: General
>    Affects Versions: 2.1.0-SNAPSHOT
>         Environment: myfaces core trunk
>            Reporter: Martin Kočí
>            Assignee: Martin Kočí
>         Attachments: MYFACES-3144.patch
>
>
> UIComponentBase uses getRenderer(): Renderer in five methods:
> 1) decode
> 2) encodeBegin
> 3) encodeChildren
> 4) encodeEnd
> 50 getClientId
> getting the renderer is not cheap if you have thousands component in view. 
> Cache renderer instance in UIComponentBase (Trinidad UIXComponentBase does it already)

--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira

       

[jira] [Resolved] (MYFACES-3144) [PERF] Cache renderer in UIComponentBase

Posted by "Leonardo Uribe (Resolved) (JIRA)" <de...@myfaces.apache.org>.
     [ https://issues.apache.org/jira/browse/MYFACES-3144?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Leonardo Uribe resolved MYFACES-3144.
-------------------------------------

       Resolution: Fixed
    Fix Version/s: 2.1.7
                   2.0.13
         Assignee: Leonardo Uribe  (was: Martin Kočí)
    
> [PERF] Cache renderer in UIComponentBase
> ----------------------------------------
>
>                 Key: MYFACES-3144
>                 URL: https://issues.apache.org/jira/browse/MYFACES-3144
>             Project: MyFaces Core
>          Issue Type: Improvement
>          Components: General
>    Affects Versions: 2.1.0-SNAPSHOT
>         Environment: myfaces core trunk
>            Reporter: Martin Kočí
>            Assignee: Leonardo Uribe
>             Fix For: 2.0.13, 2.1.7
>
>         Attachments: MYFACES-3144.patch
>
>
> UIComponentBase uses getRenderer(): Renderer in five methods:
> 1) decode
> 2) encodeBegin
> 3) encodeChildren
> 4) encodeEnd
> 50 getClientId
> getting the renderer is not cheap if you have thousands component in view. 
> Cache renderer instance in UIComponentBase (Trinidad UIXComponentBase does it already)

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators: https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira

       

[jira] [Commented] (MYFACES-3144) [PERF] Cache renderer in UIComponentBase

Posted by "Jakob Korherr (JIRA)" <de...@myfaces.apache.org>.
    [ https://issues.apache.org/jira/browse/MYFACES-3144?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13033497#comment-13033497 ] 

Jakob Korherr commented on MYFACES-3144:
----------------------------------------

> Is there any method which is always called as first if component will executed/rendered?

MyFaces internally yes, but if you use extensions for custom JSF comp-libs it might be different. We should not rely on an invariant like that!

> [PERF] Cache renderer in UIComponentBase
> ----------------------------------------
>
>                 Key: MYFACES-3144
>                 URL: https://issues.apache.org/jira/browse/MYFACES-3144
>             Project: MyFaces Core
>          Issue Type: New Feature
>          Components: General
>    Affects Versions: 2.1.0-SNAPSHOT
>         Environment: myfaces core trunk
>            Reporter: Martin Kočí
>            Assignee: Martin Kočí
>         Attachments: MYFACES-3144.patch
>
>
> UIComponentBase uses getRenderer(): Renderer in five methods:
> 1) decode
> 2) encodeBegin
> 3) encodeChildren
> 4) encodeEnd
> 50 getClientId
> getting the renderer is not cheap if you have thousands component in view. 
> Cache renderer instance in UIComponentBase (Trinidad UIXComponentBase does it already)

--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira

[jira] [Commented] (MYFACES-3144) [PERF] Cache renderer in UIComponentBase

Posted by "Martin Kočí (JIRA)" <de...@myfaces.apache.org>.
    [ https://issues.apache.org/jira/browse/MYFACES-3144?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13051213#comment-13051213 ] 

Martin Kočí commented on MYFACES-3144:
--------------------------------------

I'm little lost here ... the  patch (trinidad code) does not use String comparisions. Is that patch applicable? Trinidad is well tested (and fast).

The  performance problem is in repeated HashMap lookups. Yes, it's only minor (compared with reflexion for example). But in large view it can save thousands such lookups - minor improvement, but still improvement



> [PERF] Cache renderer in UIComponentBase
> ----------------------------------------
>
>                 Key: MYFACES-3144
>                 URL: https://issues.apache.org/jira/browse/MYFACES-3144
>             Project: MyFaces Core
>          Issue Type: New Feature
>          Components: General
>    Affects Versions: 2.1.0-SNAPSHOT
>         Environment: myfaces core trunk
>            Reporter: Martin Kočí
>            Assignee: Martin Kočí
>         Attachments: MYFACES-3144.patch
>
>
> UIComponentBase uses getRenderer(): Renderer in five methods:
> 1) decode
> 2) encodeBegin
> 3) encodeChildren
> 4) encodeEnd
> 50 getClientId
> getting the renderer is not cheap if you have thousands component in view. 
> Cache renderer instance in UIComponentBase (Trinidad UIXComponentBase does it already)

--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira

       

[jira] [Commented] (MYFACES-3144) [PERF] Cache renderer in UIComponentBase

Posted by "Leonardo Uribe (Commented) (JIRA)" <de...@myfaces.apache.org>.
    [ https://issues.apache.org/jira/browse/MYFACES-3144?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13223467#comment-13223467 ] 

Leonardo Uribe commented on MYFACES-3144:
-----------------------------------------

Thinking about it, I found an alternative solution for this problem. The idea is create two vars in UIComponentBase:

    private transient Boolean _cachedIsRendered;
    private transient Renderer _cachedRenderer;

copy the code from UIComponent.encodeAll() to UIComponentBase. Then, do the same trick for cache FacesContext, but on encodeAll(). The idea is set _cachedRendered and _cachedIsRendered at the beginning and then clear this variables before end the method.

Then, some code is added in isRendered() and getRenderer() to check for the cached var and if is set, return that value. In this way we have control about the cached var. If by some reason encodeXXX() is called instead encodeAll(), the code will work as expected. The same thing can be done in decode() method, but in this case only for _cachedRendered, preventing a second call when getClientId() is called.

In this way we can save between 6 and 8 lookups to a map. isRendered() is called only once per component, which is valid because this value does not change while encoding of the same component occur. Also, it preserves getRenderer() plugability, because it is possible to change the renderKit before render response time and reflect the change. 
                
> [PERF] Cache renderer in UIComponentBase
> ----------------------------------------
>
>                 Key: MYFACES-3144
>                 URL: https://issues.apache.org/jira/browse/MYFACES-3144
>             Project: MyFaces Core
>          Issue Type: New Feature
>          Components: General
>    Affects Versions: 2.1.0-SNAPSHOT
>         Environment: myfaces core trunk
>            Reporter: Martin Kočí
>            Assignee: Martin Kočí
>         Attachments: MYFACES-3144.patch
>
>
> UIComponentBase uses getRenderer(): Renderer in five methods:
> 1) decode
> 2) encodeBegin
> 3) encodeChildren
> 4) encodeEnd
> 50 getClientId
> getting the renderer is not cheap if you have thousands component in view. 
> Cache renderer instance in UIComponentBase (Trinidad UIXComponentBase does it already)

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators: https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira

       

[jira] [Commented] (MYFACES-3144) [PERF] Cache renderer in UIComponentBase

Posted by "Jakob Korherr (JIRA)" <de...@myfaces.apache.org>.
    [ https://issues.apache.org/jira/browse/MYFACES-3144?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13051202#comment-13051202 ] 

Jakob Korherr commented on MYFACES-3144:
----------------------------------------

I agree with Leonardo. String operations are usually not as cheap as you would think, and HashMap lookups are usually not as expensive as you would think!

However, note that normally the renderer of a component does not change at all. In most cases there is one renderer per component and also even only one render-kit: HTML_BASIC (there are really not many JSF apps using more than one renderkit at this time). So it would make sence to really implement the cache without the String comparisons of renderKitId, family and rendererType. Of course, this should only work via a custom init parameter, which is false by default, in order to allow applications with multiple renderers or renderkits to work.

> [PERF] Cache renderer in UIComponentBase
> ----------------------------------------
>
>                 Key: MYFACES-3144
>                 URL: https://issues.apache.org/jira/browse/MYFACES-3144
>             Project: MyFaces Core
>          Issue Type: New Feature
>          Components: General
>    Affects Versions: 2.1.0-SNAPSHOT
>         Environment: myfaces core trunk
>            Reporter: Martin Kočí
>            Assignee: Martin Kočí
>         Attachments: MYFACES-3144.patch
>
>
> UIComponentBase uses getRenderer(): Renderer in five methods:
> 1) decode
> 2) encodeBegin
> 3) encodeChildren
> 4) encodeEnd
> 50 getClientId
> getting the renderer is not cheap if you have thousands component in view. 
> Cache renderer instance in UIComponentBase (Trinidad UIXComponentBase does it already)

--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira