by John Brinkman
April 22, 2009
Clearly there are differences. I was surprised at how much faster the FormCalc version was. I would like to understand that better some day.
The Game of Life FormA few notes about how the form works:
- Each cell is a check box field. You can re-arrange the starting pattern by toggling the fields
- The grid is initialized by creating nested row/column subforms
- The row and column subforms are renamed so that the object expressions don’t use indexes. e.g. grid.row.column becomes grid.row_3.column_4
vNeighbourCount = 0; vNeighbourCount += form1.grid.row_2.column_3.cell.rawValue; vNeighbourCount += form1.grid.row_3.column_3.cell.rawValue; vNeighbourCount += form1.grid.row_4.column_3.cell.rawValue; vNeighbourCount += form1.grid.row_2.column_4.cell.rawValue; vNeighbourCount += form1.grid.row_4.column_4.cell.rawValue; vNeighbourCount += form1.grid.row_2.column_5.cell.rawValue; vNeighbourCount += form1.grid.row_3.column_5.cell.rawValue; vNeighbourCount += form1.grid.row_4.column_5.cell.rawValue; if (form1.grid.row_3.column_4.cell.rawValue) vNewState = (vNeighbourCount == 2 || vNeighbourCount == 3) ?1:0; else vNewState = (vNeighbourCount == 3) ? 1:0; form1.grid.row_3.column_4.cell.extras.newState.value = vNewState;After one pass where we stored the new state for each of the cells in the extras of the cell field, we assign the new state:
vNeighbourCount=0; vNeighbourCount += this.resolveNode(“form1.grid.row_2.column_3.cell”).rawValue; vNeighbourCount += this.resolveNode(“form1.grid.row_3.column_3.cell”).rawValue; vNeighbourCount += this.resolveNode(“form1.grid.row_4.column_3.cell”).rawValue; vNeighbourCount += this.resolveNode(“form1.grid.row_2.column_4.cell”).rawValue; vNeighbourCount += this.resolveNode(“form1.grid.row_4.column_4.cell”).rawValue; vNeighbourCount += this.resolveNode(“form1.grid.row_2.column_5.cell”).rawValue; vNeighbourCount += this.resolveNode(“form1.grid.row_3.column_5.cell”).rawValue; vNeighbourCount += this.resolveNode(“form1.grid.row_4.column_5.cell”).rawValue; if (this.resolveNode(“form1.grid.row_3.column_4.cell”).rawValue) vNewState = (vNeighbourCount == 2 || vNeighbourCount == 3) ?1:0; else vNewState = (vNeighbourCount == 3) ? 1 : 0; this.resolveNode (“form1.grid.row_3.column_4.cell.extras.newState”).value = vNewState;And one more comparison where we do the same in FormCalc:
vNeighbourCount = 0 vNeighbourCount = vNeighbourCount + form1.grid.row_2.column_3.cell vNeighbourCount = vNeighbourCount + form1.grid.row_3.column_3.cell vNeighbourCount = vNeighbourCount + form1.grid.row_4.column_3.cell vNeighbourCount = vNeighbourCount + form1.grid.row_2.column_4.cell vNeighbourCount = vNeighbourCount + form1.grid.row_4.column_4.cell vNeighbourCount = vNeighbourCount + form1.grid.row_2.column_5.cell vNeighbourCount = vNeighbourCount + form1.grid.row_3.column_5.cell vNeighbourCount = vNeighbourCount + form1.grid.row_4.column_5.cell if (form1.grid.row_3.column_4.cell) then vNewState = if(vNeighbourCount == 2 or vNeighbourCount == 3,1,0) else vNewState = if(vNeighbourCount == 3, 1, 0) endif form1.grid.row_3.column_4.cell.extras.newState = vNewState;
ResultsThe good news is, that all three variations are *very* slow — great for measuring performance :-) The performance results when I ran this on my laptop:
|JS with Object Expressions||JS with calls to resolveNode()||FormCalc|
|Milliseconds per Expression||0.243||0.159||0.059|
var foo = “hello world”; xfa.host.messageBox(foo);is handled differently from
for (var i=0; i<10000; i++) total += po.nodes.item(i).subtotal.rawValue;vs.
for (i=0; i<10000; i++) total += po.nodes.item(i).subtotal.rawValue;In the first case, the XFA processor evaluates “i” once. In the second case, the XFA processor evaluates “i” 30,000 times. Would you notice the difference? It depends on two factors:
- How many iterations in the loop and how many references to the loop counter
- The cost of one lookup – how many objects are in scope when we do the evaluation. When the XFA processor searches for “i”, it does a physical scan through all objects that are within scope of the current context.