简体   繁体   中英

setTimeout in javascript make function run faster

I have an application which I have to push a lot values to array, so I test the execution time:

var st = new Date().getTime();
var a = [];
for (var i = 0; i < 20971520; i++) {
  a.push(i);
}
var ed = new Date().getTime();
console.info((ed - st) / 1000);
console.info(a.length);

I run the codes in Firefox Console and Chrome console directly, and it cost 37 seconds . And during the execution, even the mouse can be moved in Chrome, but there is no interactive effect.

Then I change the codes:

function push() {
  var st = new Date().getTime();
  var a = [];
  for (var i = 0; i < 20971520; i++) {
    a.push(i);
  }
  var ed = new Date().getTime();
  console.info((ed - st) / 1000);
  console.info(a.length);
}

var tr = setTimeout(push, 50);

Simplify put the codes in a function, and call it using the setTimeout , it cost 0.844 second . And during the execution, I can operation in Chrome normally.

控制台截图

What's going on here?

I know that the setTimeout will put the control to the browser to do the UI job, which will make the page responsive. For example, when I do some calculation during the mousemove of the page, I would put the calculation executed delayed to prevent it blocking the UI.

But why it reduce the total execution time of the same codes?

And during the execution, I can operation in Chrome normally.

Not true. The main chrome window will be just as frozen as the other case (just for a shorter while). The debug tools are a separate thread and will not slow down though.

But why it reduce the total execution time of the same codes?

It does if you run in dev tools. If you execute the code in actuality where the VM can make property optimizations the times are comparable (nearly 1 second). eg

   var st = new Date().getTime();
   var a = [];
   for (var i = 0; i < 20971520; i++) {
       a.push(i);
   }
   var ed = new Date().getTime();
   console.info('normal', (ed - st) / 1000);
   console.info(a.length);

   function push() {
       var st = new Date().getTime();
       var a = [];
       for (var i = 0; i < 20971520; i++) {
           a.push(i);
       }
       var ed = new Date().getTime();
       console.info('timeout', (ed - st) / 1000);
       console.info(a.length);
   }

   var tr = setTimeout(push, 0);

http://jsfiddle.net/gu9Lg52j/ you will see the normal executes just as fast as setTimeout .

Also if you wrap the code in a function and execute in a console the time will be comparable even without a setTimeout as the VM can make optimizations between function definition and execution:

  function push() {
       var st = new Date().getTime();
       var a = [];
       for (var i = 0; i < 20971520; i++) {
           a.push(i);
       }
       var ed = new Date().getTime();
       console.info('timeout', (ed - st) / 1000);
       console.info(a.length);
   }
   push();

Both variations of code should run with almost identical speed (the latter example might be faster but not 10 times faster).

Inside the Chrome developer tools, there is a different story. The expressions are evaluated inside a with block. This means the variables such as a and i are first searched inside another object (the __commandLineAPI ). This adds an additional overhead which results in the 10 times longer execution time.

All JavaScript engines perform various optimizations. For example V8 uses 2 compilers, a simple one used by default and an optimizing one. Code not compiled by the optimizing compiler is slow , very slow.

A condition for the optimizing compiler to run is that the code must be in a (not too long) function ( there are other conditions ). The first code you tried in the console isn't in a function. Put your first code in a function and you'll see it performs the same than the second one, setTimeout changes nothing.

It makes zero sense to check for performances in the console when the main performance factor is the optimizing compilation. If you're targeting node, use a benchmarking framework. If you're targeting the browser, use a site like jsperf .

Now, when you have to do a really long computation in the browser (which doesn't seem to be the case here), you should consider using web workers which do the job in a background thread not impacting the UI.

setTimeout , like others noticed, doesn't speed up the array creation and does lock the browser. If you are concerned about browser lockup during the array creation, web workers (see MDN ) may come to the rescue. Here is a jsFiddle demo using a web worker for your code. The worker code is within the html:

onmessage = function (e) {
   var a = [], now = new Date;
   for (var i=0; i<20971520; i++) {
     a.push(i);
   }
   postMessage({timings: 'duration: '+(new Date()-now) + 
                         'Ms, result: [' + a[0] + '...'+a[a.length-1] + ']'});
 }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM