forum

Home / DeveloperSection / Forums / How to break up a long running function in javascript, but keep performance

How to break up a long running function in javascript, but keep performance

Pravesh Singh218403-May-2013
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!

Updated on 03-May-2013

Can you answer this question?


Answer

1 Answers

Liked By