javascript中的setTimeout让函数运行得更快

时间:2015-01-06 08:30:49

标签: javascript date settimeout

我有一个应用程序,我必须将很多值推送到数组,所以我测试执行时间:

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);

我直接在Firefox控制台和Chrome控制台中运行代码,费用为37 seconds。在执行过程中,即使鼠标也可以在Chrome中移动,但没有交互效果。

然后我改变了代码:

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);

简化将代码放入函数中,并使用setTimeout调用它,费用为0.844 second。在执行期间,我可以正常在Chrome中操作。

Screenshot of console

这里发生了什么?

我知道setTimeout会将控件放到浏览器上来执行UI作业,这会使页面响应。例如,当我在页面的鼠标移动期间进行一些计算时,我会将计算执行延迟以防止它阻止UI。

但为什么它会减少相同代码的总执行时间?

4 个答案:

答案 0 :(得分:5)

  

在执行期间,我可以正常在Chrome中操作。

不正确。主要的镀铬窗口将与其他情况一样冷冻(仅适用于较短的时间)。调试工具是一个单独的线程,但不会减慢速度。

  

但为什么它会减少相同代码的总执行时间?

如果你在dev工具中运行它会。如果您实际执行代码,VM可以进行属性优化,则时间可比(近1秒)。例如

   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/您会看到normal执行setTimeout一样快

此外,如果您将代码包装在函数中并在控制台中执行,即使没有setTimeout,时间也是可比较的,因为VM可以在函数定义和执行之间进行优化:

  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();

答案 1 :(得分:2)

代码的两种变体应该以几乎相同的速度运行(后一个示例可能更快,但速度不快10倍)。

在Chrome开发者工具中,有一个不同的故事。表达式在with块内进行评估。这意味着首先在另一个对象(__commandLineAPI)内搜索ai等变量。这会增加额外的开销,导致执行时间延长10倍。

答案 2 :(得分:1)

所有JavaScript引擎都执行各种优化。例如,V8使用2个编译器,一个默认使用的简单编译器和一个优化编译器。优化编译器未编译的代码,非常慢。

优化编译器运行的条件是代码必须在(不太长)函数(there are other conditions)中。您在控制台中尝试的第一个代码不在函数中。将您的第一个代码放在一个函数中,你会看到它的表现与第二个相同,setTimeout不会改变任何内容。

当主要性能因素是优化编译时,检查控制台中的性能是没有意义的。如果您的目标是节点,请使用基准测试框架。如果您要定位浏览器,请使用jsperf等网站。

现在,当你必须在浏览器中进行一个非常长的计算时(这里似乎不是这种情况),你应该考虑在不影响UI的后台线程中完成工作的using web workers

答案 3 :(得分:0)

像其他人注意到的那样,{p> setTimeout不会加快阵列创建速度,而锁定浏览器。如果您担心阵列创建期间的浏览器锁定, Web worker (请参阅MDN)可能会解决问题。这是一个使用Web worker为您的代码进行的jsFiddle演示。工作人员代码在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] + ']'});
 }