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

问题描述 投票:5回答:4

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

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中操作。

这里发生了什么?

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

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

javascript date settimeout
4个回答
5
投票

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

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

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

如果您使用开发工具运行它。如果您实际执行代码,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();

2
投票

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

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


1
投票

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

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

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

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


0
投票

像其他人注意到的那样,setTimeout不会加速阵列创建并锁定浏览器。如果您担心在阵列创建期间浏览器锁定,Web工作人员(请参阅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] + ']'});
 }
© www.soinside.com 2019 - 2024. All rights reserved.