HOW TO BREAK UP A LONG RUNNING FUNCTION IN JAVASCRIPT, BUT KEEP PERFORMANCE

Pravesh Singh

Total Post:412

Points:2888
Posted by  Pravesh Singh
 1333  View(s)
Ratings:
Rate this:
Hi Expert!

I have a long running function. Which iterates through a large array and performs a function within each loop.

longFunction : function(){
       var self = this;
       var data = self.data;

       for(var i=0; len = data.length; i<len; i++){
              self.smallFunction(i);
       }
},
smallFunction : function(index){

// Do Stuff!

}
For the most part this is fine but when I am dealing with arrays above around 1500 or so we get to the point of recieving a javascript execution alert message.

So I need to break this up. My first attempt is like so:

longFunction : function(index){
       var self = this;
       var data = self.data;


      self.smallFunction(index);

      if(data.slides[index+1){
         setTimeout(function(){
            self.longFunction(index+1);
         },0);
      }
      else {
               //WORK FINISHED
      }

},
smallFunction : function(index){

// Do Stuff!

}
So here I am removing the loop and introducing a self calling function which increases its index each iteration. To return control to the main UI thread in order to 

prevent the javascript execution warning method I have added a setTimeout to allow it time to update after each iteration. The problem is that with this method 

getting the actual work done takes quite literally 10 times longer. What appears to be happening is although the setTimeout is set to 0, it is actually waiting more 

like 10ms. which on large arrays builds up very quickly. Removing the setTimeout and letting longFunction call itself gives performance comparable to the original 

loop method.

I need another solution, one which has comparable performance to the loop but which does not cause a javascript execution warning. Unfortunately webWorkers cannot be 

used in this instance.

It is important to note that I do not need a fully responsive UI during this process. Just enough to update a progress bar every few seconds.

Would breaking it up into chunks of loops be an option? I.e. perform 500 iterations at a time, stop, timeout, update progress bar, perform next 500 etc.. etc..

Is there anything better?

ANSWER:

The only solution seems to be chunking the work.

By adding the following to my self calling function I am allowing the UI to update every 250 iterations:

 longFunction : function(index){
           var self = this;
           var data = self.data;


          self.smallFunction(index);

          var nextindex = i+1;

          if(data.slides[nextindex){
            if(nextindex % 250 === 0){
             setTimeout(function(){               
                self.longFunction(nextindex);
             },0);
            }
            else {
                self.longFunction(nextindex);
            }
          }
          else {
                   //WORK FINISHED
          }

    },
    smallFunction : function(index){

    // Do Stuff!

    }
All I am doing here is checking if the next index is divisible by 250, if it is then we use a timeout to allow the main UI thread to update. If not we call it again directly.

Please help me!
  1. AVADHESH PATEL

    Post:604

    Points:4228
    Re: How to break up a long running function in javascript, but keep performance

    Hi Pravesh!


    Here's some batching code modified from an earlier answer I had written:

    var n = 0,
        max = data.length;
        batch = 100;

    (function nextBatch() {
        for (var i = 0; i < batch && n < max; ++i, ++n) {
            myFunc(n);
        }
        if (n < max) {
            setTimeout(nextBatch, 0);
        }
    })();

    I hope it resolve your problem!

Answer

NEWSLETTER

Enter your email address here always to be updated. We promise not to spam!