Skip navigation
Currently Being Moderated

Dynamic Form is painfully slow to open and edit

May 11, 2012 11:57 AM

I'm hoping someone could take a few minutes and see if they could help me figure out why this form 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've tried removing the page numbering in the layout:ready event and it doesn't help the performance at all. I do have a lot of calculations and a lot of resolveNodes, but I don't think I have any other way of performing these calculations without them. If anyone could point me in the right direction.

 

The form is here:

https://acrobat.com/#d=pBkuyHMzab36bS4N0U9VEg

...and if you open it in Acrobat or Reader first, you'll see what I mean. It's not as slow in a preview in Livecycle because all of the entered data is gone.

 

Thank you for any help.

 

Jo

 
Replies
  • Currently Being Moderated
    May 13, 2012 9:43 PM   in reply to joflo723

    Hi, Most of the processing time seems to be spent in calculating the clientTotals, you have 8 total fields all looping though the same structures, you could move this calculations to the clientTotals subform and save some of the looping.

     

    This is an example of the form with some console messages giving the execution time for each event.  https://acrobat.com/#d=aZDO3dMHAiAda*IuGURmCQ

     

    Each one of the clientTotals calculations are taking about 325ms on my machine, and you have three rows of eight fields.

     

    Hope this helps

     

    Bruce

     
    |
    Mark as:
  • Currently Being Moderated
    May 14, 2012 2:30 AM   in reply to BR001

    Here's the performance analysis of your form.

     

    As Bruce indicated, you have violated the numericEdit is violating max allowable occurences. You should restrict the some loops.

     

    Fields 43

    Subform 12

    Font Count : 43

    calculate (JavaScript) : 153 (Line of Script)

    enter (JavaScript) : 112 (Line of Script).

     
    |
    Mark as:
  • Currently Being Moderated
    May 14, 2012 9:48 AM   in reply to joflo723

    If you don't have a specific requirement for JavaScript, FormCalc would speed things up the most and be a lot easier to write.

     

    The asterisk in the square brackets is what handles repeating items.

     

    Just looking at your repTotals.correspTotal field the FormCalc code would be:

    $ = sum(ItemSet[*].corresp)

     

    Or using the method John Brinkman shows with JavaScript:

    var sum = 0;

    var rows = this.resolveNodes("ItemSet[*].corresp");

    var len = rows.length;

    for (var i = 0; i < len; i++) {

              sum += rows.item(i).rawValue;

    }

    sum;

     
    |
    Mark as:
  • Currently Being Moderated
    May 14, 2012 2:19 PM   in reply to joflo723

    So expanding on John's sample I tried the following which worked but may not be the best way to go about it - hopefully Bruce will chime in, I'm not the greatest programmer.

     

    It's definitely faster when I tested using Bruce's timer routine but I haven't had a chance to try it on the client totals section which is the one that's sucking most of the time - I think it should speed things up a fair bit there. Hopefully you can extrapolate this to work in your client totals section.

     

    FormCalc would still be faster but I haven't done much with loops in FormCalc.

     

    var sum = 0;

    var rows = this.resolveNodes("ItemSet[*].corresp");

    var oClient = this.resolveNodes("ItemSet[*].client");

    var len = rows.length;

    for (var i = 0; i < len; i++) {

              if (oClient.item(i).rawValue == clientName.rawValue) {

                        sum += rows.item(i).rawValue;

              }

    }

    sum;

     
    |
    Mark as:
  • Currently Being Moderated
    May 14, 2012 6:48 PM   in reply to Jono Moore

    To increase further performance, you must not embed the fonts unless it an absolute neccessity. Adding subforms, allow to structure things properly and effective scripting. But adding too many subforms reduce performance. It's always a best to keep the count minimal.

     

    One question, does your form require server side Data binding ? If not, uncheck the option under Form Properties.

     
    |
    Mark as:
  • Currently Being Moderated
    May 15, 2012 1:53 AM   in reply to Deepak Chauhan

    Hi,

     

    I would like to try removing the two resolveNodes calls and the two item methods from Jono's example and see if that helped, so;

     

    var result = 0;

    var rows = this.resolveNodes("ItemSet[*]");

    for (var i=0, limit=rows.length; i<limit; i++)

    {

        var row = rows.item(i);

        if (row.client.rawValue === clientName.rawValue)

        {

            result += row.corresp.rawValue

        }

    }

    result;

     

    But I have not timed this and am still surprised about being wrong with optimisations.

     

    I think the big win is to remove the code from the calculate events of the the fields correspTotal, hcfaTotal, holdsMiscTotal, Total182, Total215, Total247, Total259 and Total268 (I renamed Total268 as it was a duplicate and complicated my script) and add the following code to the calculate event of clientTotals (the parent subform), so you only loop though your form once per client.

     

    var correspTotalWork = 0;

    var hcfaTotalWork = 0;

    var holdsMiscTotalWork = 0;

    var total182Work = 0;

    var total215Work = 0;

    var total247Work = 0;

    var total259Work = 0;

    var total268Work = 0;

     

    var reps = P1.resolveNodes("rep[*]");

    var repCount = reps.length;

    for (var j=0; j<repCount; j++)

    {

        var rep = reps.item(j);

        var itemSets = rep.resolveNodes("ItemSet[*]");

        var itemSetCount = itemSets.length;

        for (var i=0; i<itemSetCount; i++

        {

            var itemSet = itemSets.item(i);

            if (itemSet.client.rawValue === clientName.rawValue)

            {

                if (itemSet.corresp.rawValue > 0)

                {

                    console.println(itemSet.client.rawValue+" "+itemSet.corresp.rawValue);

                }

                correspTotalWork += itemSet.corresp.rawValue;

                hcfaTotalWork += itemSet.hcfa.rawValue;

                holdsMiscTotalWork += itemSet.holdsMisc.rawValue;

                total182Work += itemSet.tic182.rawValue;

                total215Work += itemSet.tic215.rawValue;

                total247Work += itemSet.tic247.rawValue;

                total259Work += itemSet.tic259.rawValue;

                total268Work += itemSet.tic268.rawValue;

            }

        }

    }

    correspTotal.rawValue = correspTotalWork;

    hcfaTotal.rawValue = hcfaTotalWork;

    holdsMiscTotal.rawValue = holdsMiscTotalWork;

    Total182.rawValue = total182Work;

    Total215.rawValue = total215Work;

    Total247.rawValue = total247Work;

    Total259.rawValue = total259Work;

    Total268.rawValue = total268Work;

     

    The next step you could try would be to loop though the form once and maintain the eight totals per client.

     

    To see the console messages in my previous example press Ctrl-J.  You should see some lines like;

     

    form1.P1.rep.repTotals.Total268.#calculate:Time elapsed 3ms

    form1.P1.rep.repTotals.unresolvedTotal.#calculate:Time elapsed 3ms

    form1.clientTotals.correspTotal.#calculate:Time elapsed 340ms

    form1.clientTotals.hcfaTotal.#calculate:Time elapsed 358ms

     

    Good luck

     

    Bruce

     
    |
    Mark as:
  • Currently Being Moderated
    May 15, 2012 3:05 PM   in reply to joflo723

    Hi Jo,

     

    You may have to add in a reference to the instanceManager occurance number, see the second line.

     

    var result = 0;

    var limit = rep._ItemSet.count;

    var rows = this.resolveNodes("ItemSet[*]");

    for (var i=0, limit=rows.length; i<limit; i++)

    {

        var row = rows.item(i);

        if (row.client.rawValue === clientName.rawValue)

        {

            result += row.corresp.rawValue

        }

    }

    result;

     

    You don't have to do anything with the value but just referencing is enought to cause the calculate event to fire when it's value changes.

     

    Also, I notice that all your fields are defined as float, if your values are all integer then you can define them as integer on the Binding tab of the Object palette.  Maybe it will handle integers quicker?

     

    Bruce

     
    |
    Mark as:
  • Currently Being Moderated
    May 16, 2012 7:50 PM   in reply to joflo723

    Hi,

     

    Try moving the execCalculate call you added to the add line button, so

     

    form1.P1.rep.Subform1.Button1::click - (JavaScript, client)

    rep.ItemSet.instanceManager.addInstance();

    P1.rep.execInitialize();

    clientTotals.execCalculate();

     

    Bruce

     
    |
    Mark as:
  • Currently Being Moderated
    May 17, 2012 10:01 AM   in reply to joflo723

    Thanks Bruce. That would probably work, but it isn't doing anything when I click. I think it may be because it should be:

     

    clientTotals[*].execCalculate();

     

    ...so that it runs on ALL instances of the clientTotals subform. But that's FormCalc and I am using Javascript on this button already. Is there a way to use FormCalc and Javascript on the same object? Otherwise, is there a javascript alternative to this statement?

     

    You'd need a loop like the other loops but this time firing execCalculate. You can use FormCalc and JavaScript on the same object, just not the same event. So on a button you could use events like mouseUp/mouseDown/Click etc. to split things up. You could also have another hidden button that you fire with the first button.

     

    Are things running much faster overall?

     

    I was thinking some more about your form and depending on how large it gets you will probably still end up with things slowing down. The problem with using the calculate event is that every time something changes in the form the calculate event fires, so there's lots of wasted calculations going on.

     

    One way around this may be to put your client total calculations onto a button that the user clicks when they want to refresh the totals, this would make things less frustrating for the person trying to do stuff in the form. And also as you noted above on the presave or preprint events.

     
    |
    Mark as:

More Like This

  • Retrieving data ...

Bookmarked By (0)

Answers + Points = Status

  • 10 points awarded for Correct Answers
  • 5 points awarded for Helpful Answers
  • 10,000+ points
  • 1,001-10,000 points
  • 501-1,000 points
  • 5-500 points