UIData performance improvements
-------------------------------

                 Key: MYFACES-3236
                 URL: https://issues.apache.org/jira/browse/MYFACES-3236
             Project: MyFaces Core
          Issue Type: Improvement
          Components: JSR-314
    Affects Versions: 2.1.1, 2.0.7
            Reporter: Leonardo Uribe
            Assignee: Leonardo Uribe


Some days ago there was a discussion on dev list titled:

[core] performance: performance hints

With the following intention (proposed by Martin Koci):

    MK>> is it possible to introduce performance hints in myfaces-core? Hints
    MK>> similar to javax.faces.component.visit.VisitHint but related to
    MK>> performance improvements. Example:
    
    MK>> For dataTable like:
    MK>> <a:dataTable
    MK>> <a:column>
    MK>>     #{aExpression}
    
    MK>> it's completely unnecessary to save per-row state. Currently there is 
no
    MK>> elegant way how to do read-only table (state per-row is always
    MK>> maintained). If user wants (fast) readOnly table, he/she must extend
    MK>> UIData and re-implemenent setRowIndex method. But hint say
    MK>> "org.apache.myfaces.core.UIData.saveRowState"=false can solve it
    MK>> elegantly - if present (in component.getAttributes()) UIData skips
    MK>> row-state-saving and restoring methods entirely.
    
    MK>> Lifespan of those hints can be request (faceContext.attributes) or view
    MK>> (component.attributes)
    
The discussion there was to create or not a hint but a review of the default 
algorithm was never done. In theory, UIData.setRowIndex do the following tasks:

1. If the component is in row -1 (no row), take a "snapshot" of the components 
that implements EditableValueHolder, to restore them later when rows are 
traversed.
2. If the component is in a row, save the current state of EditableValueHolder 
components.
3. Move to the selected row.
4. If no state saved found, restore EditableValueHolder components from saved 
initial state.
5. If state saved found, restore EditableValueHolder components from stored 
saved state.  

After an in-deep analysis, the conclusion was it is not really necessary to 
create the hint. Instead, we can create a better algorithm that take advantage 
of 
the fact that add a non transient EditableValueHolder component inside a 
dataTable row on render response time leads to a illegal state.

Since UIData.setRowIndex is a code that is called multiple times, specially for 
large datatable sets. Doing some performance tests, it was notice the current 
algorithm uses a lot of memory resources. The proposal is do the following:

1. Iterate using index instead iterator for children. This can duplicate the 
lines of code 
2. Do not create Object[]{null,null} instances, use a private static final 
variable.
3. Cache DataListener[].
4. If no EditableValueHolder instances found, skip state saving code, but reset 
all ids.
5. Prevent unnecessary calls to getContainerClientId().
6. Provide initial size for created ArrayList instances to reduce memory usage.
7. Iterate over row state using index, instead iterator, and take advantage 
instances are ArrayList.
8. Do not instantiate ArrayList, unless it is necessary.
 
Tests done shows a really big improvement, specially when non 
EditableValueHolder component instances are inside the datatable, which is a 
very common use case.

Based on this patch we can do other things like:

1. Port this code to UIRepeat.
2. Port this code to Tomahawk.
3. Reuse already created state instances, which can improve performance on 
postback requests.

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

        

Reply via email to