Projects‎ > ‎

XForms - Insert and Delete Performance Improvements and Controls Tree Improvements

NOTE: This was implemented in August 2008.

Rationale

Facts:
  • Currently (before 2008-08-20), insert and delete are costly because in order to update repeat indexes, they rebuild controls entirely. This is very visible in large applications that perform lots of instance modifications, including Form Builder, where 100s of ms can be spent rebuilding controls.
  • XForms 1.1 specifies index updates better, by saying that only repeat iterations should be updated right away.
So we think we can avoid these expensive rebuilds by being smarter. This will even get us more compliance.

NOTE: In the big scheme of things, the XForms 1.1 proposal for repeat iterations updates is a fairly crude dependency mechanism, but this could be improved in the future based on our experiences in this area.

Proposal

First phase:
  • insert, delete, setindex(?) determine which repeats are impacted
  • use xforms-insert and xforms-delete events to hook-up following behavior
  • in this phase, we do immediate updates after each insert/delete, which is not optimal but should be acceptable
  • repeat iterations are updated accordingly
    • updateControlsOnDelete
      • remove iterations
    • updateControlsOnInsert
      • add iterations
      • create subtrees of controls
  • new indexes are set
Second phase [NOT SURE HOW MUCH THIS WOULD BUY US]:
  • updates can be "batched"
    • controls (here repeats) are marked dirty
    • dirty controls are updated lazily
      • upon using index(id)
      • upon referring to controls within dirty subtrees
    • upon refresh, everything is brought up to date
  • once real UI controls dependency mechanism is in place
    • this mechanism can be applied to all controls

Implementation Notes

These notes relate to the implementation done between 2008-08-20 and 2008-08-26:
  • refactored out handling of switches and indexes out of insert/delete actions
  • XFormsInstance processes xforms-insert / xforms-delete
  • incremental updates to current tree
    • find differences between old and new repeat nodesets
    • if there is a difference:
      • two cases
        • for nodes that existed
          • keep the RepeatIterationControl 
          • update iteration index and nested effective ids if iteration index has changed
        • for new nodes
          • create new RepeatIterationControl 
      • control tree effectiveId map is updated appropriately
  • repeat index handling refactoring
    • XFormsRepeatControl now keeps its own repeat index
    • ControlsState no longer holds the size of each repeat
      • -> to get it, find the repeat and call XFormsRepeatControl.getSize()
    • some of the controls initialization code has been refactored (XFormsControls.initialize())
    • index update upon insert / delete implements XForms 1.1 logic
  • switch and dialog state is no longer stored separately
  • XFormsControl: serializeLocal()/deserializeLocal()
    • repeat: index
    • switch: selected case
    • dialog: visible, neighbor, constrainToViewport
    • other controls can easily add to that
  • XFormsControlLocal: new way of handling mutable local control state which cannot be recreated from instances
  • do DIVs diffs (xforms:switch/xforms:case, xxforms:dialog) within controls diff
  • no longer rebuild tree of controls, but instead:
    • store local modifications (index, etc.)
    • clone tree when we know we will modify its content beyond local modifications
      • NOTE: we clone "back", that is we create the initial version of the controls used for comparison, when needed
    • update bindings when bindings are dirty
  • XFormsIndexUtils is gone
    • index updates are done in XFormsRepeatControl
  • XFormsSwitchUtils is gone
    • switch state is automatically kept within controls as they are not deleted
    • new iterations no longer copy the switch state: they initialize to the default switch state
  • ControlsState is now called ControlsTree and separate from XFormsControls
  • don't clone controls during sending out initial HTML

Low-Hanging Fruits for Further Optimizations

  • repeat-table-cells example with lots of rows and columns
    • it may take 100s of ms to reevaluate the controls when just the index has changed; if index() is not used, should be quite optimizable
    • same situation when changing cell in Form Builder
  • dialogs:
    • we can avoid recursing within dialogs
      • issues
        • nested variables when we dispatch events to the dialog
        • possible dispatching of events to children of the dialog when closed
        • when diffing, closed dialog should be considered non-relevant
      • when dialog becomes visible, update its bindings
  • set initial = current on XFormsControls to save memory
    • just after sending out HTML
    • just after sending out diffs instead of doing it upon incoming request
  • Question: does this refactoring allow changing the way XFormsContainer is handled?
    • -> can XFormsContainer simply be implemented by XXFormsComponentControl?
    • -> what about state restoration? use serialize/deserialize mechanism?

Comments