Wednesday, 14 January 2015

Implementing Thread Yield in Javascript

I had a problem developing for the Samsung Smart TV where there was a lot of data coming back from an Ajax request. The time it took to process the data from the Ajax request was halting UI responsiveness. Basically the UI would stop reacting to the user while this data was being processed, which on the TVs limited CPU power took about 20 seconds.

Normally with a language that supports multithreaded processing you would just run the process in a background thread. What can we do in Javascript where we only have one thread?

The Magic


There is a concept in threading called Yield that halts the current thread and allows another threads to run. We could do the same thing by turning what is normally a loop with a Thread.Yield call into tail recursion using setTimeout.

The Novelty

var processWithYield = function(total, chunkSize, processData, onComplete) {

 var processNextChunk = function(begin) {
  
  if (begin < total) {
   
   var end = begin + chunkSize;
   if (end > total) {
    end = total;
   }
  
   console.log("begin "+begin+", end "+end);
   processData(begin, end);
   
   console.log("Done processing, now we are setting next timeout beginning at "+end);
   // Yield the thread by processing the next chunk in 100 milliseconds instead of right away.
   setTimeout(function() {
    processNextChunk(end);
   }, 100);
  } else {
   console.log("All processing completed");
   onComplete();
  }
 };
 processNextChunk(0);
};

Variability


I would tweak the timeout length and the chunkSize until I had the desired data processing time vs. UI responsiveness ratio I wanted.

Further Research


Rather than using a chunkSize and a timeout length the time could be used to determine when a yield should be done. The time could be checked each iteration, then the processData function would only take one row at a time. If checking the time itself was costly in terms of CPU it could only be done once every 2 or more iterations depending on the time it takes to perform one iteration.

No comments:

Post a Comment