Script Performance Exercise

I enjoyed attending MAX last week. The best part was putting some faces to names of people who had previously been cyber-personalities.

We did a pre-conference lab on LiveCycle best practices. For the lab I prepared four exercises on various aspects of form design.  For those who weren’t able to attend, I’ll post those exercises as a series of blog entries.

Exercise #1: Measure and Improve JavaScript Performance

In this exercise we optimized a fairly simple script – a few lines in a loop. Depending on your machine, you should be able to improve the performance anywhere from a factor of three up to a factor of seven.

Open EX1 Performance Tests.pdf in Designer.

There are 50 subtotal values that need to be totaled. Each total has a test button that executes the Total script 500 times and measures the performance.

Note the 4 variations of the sum function:

  • Test 1: The original (slow) version of the calculation
  • Test 2: A copy of Test 1 that you will improve. 
    Look at the hints in the code comments in order to improve the script.
  • Test 3: The solution
  • Test4: Same calculation expressed in FormCalc

Understanding the solution:

  • Undeclared variables are very expensive to reference
  • Javascript variables are far less expensive to reference than XFA objects
  • Evaluate as few dots as possible. e.g. c.d is faster than a.b.c.d
  • Dots evaluated inside a resolveNode(s) expression are faster than dots evaluated in JavaScript objects. E.g. resolveNode("a.b.c") is faster than a.b.c

Why is FormCalc faster?

All references to XFA objects from JavaScript involve a round-trip from the script environment to the XFA processor and back. These round trips are expensive. 

FormCalc runs native in the XFA processor and there are no round-tripping costs.

5 Responses to Script Performance Exercise

  1. Keith Gross says:

    You can speed version 3 up a bit more if your willing to do a bit of house keeping elsewhere that allows you to remove the resolveNodes call. I did a version that supposed the repeating group was static. I declared an array variable within the testRunner script block and in the initialize event on the subtotal field I had the fields push themselves into this array. Then in the calculate I simply retreived this array and looped over it. In the end my times worked out as follows.

    test 1 – 3.37
    test 2 – 0.59 My optimized version
    test 3 – 1.44
    test 4 – 0.39

    Still doesn’t quite match FormCalc but pretty close.

    • John Brinkman says:

      Keith:
      You’re absolutely right. Yes, there would be extra housekeeping, but clearly lots of pay-back for your effort. I like it.

      John

  2. c@tc.se says:

    // Sticking to the original problem
    var rows = Rows.resolveNodes(“Row[*].subtotal”); // 10% boost

  3. John Brinkman says:

    c:
    that improvement makes sense one less dot to process

    John

  4. Joanne says:

    John, is it possible to use this technique in a dynamically expanding table? I have a form that I am having terrible performance issues with. The user can dynamically add rows, so I don’t know any way around using resolveNode. My filled form is here:
    https://acrobat.com/#d=pBkuyHMzab36bS4N0U9VEg
    As you will see, it is so slow to 1) open, 2) add a new line, and 3) select a client in the dropdown box in the “CLIENT” column. I would like to try the technique you have described here, but don’t know that I can in this type of form. Can you help me out with this?
    Thanks John!
    Joanne