Uploaded image for project: 'MyFaces Core'
  1. MyFaces Core
  2. MYFACES-3236

UIData performance improvements

    XMLWordPrintableJSON

Details

    • Improvement
    • Status: Closed
    • Major
    • Resolution: Fixed
    • 2.0.7, 2.1.1
    • 1.2.11, 2.0.8, 2.1.2
    • JSR-314
    • None

    Description

      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.

      Attachments

        Activity

          People

            lu4242 Leonardo Uribe
            lu4242 Leonardo Uribe
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: