了解JavaScript性能差异

时间:2014-08-03 20:46:40

标签: javascript performance

http://jsfiddle.net/6L2pJ/

var test = function () {
    var i,
        a,
        startTime;

    startTime = new Date().getTime();

    for (i = 0; i < 3000000000; i = i + 1) {
        a = i % 5;   
    }
    console.log(a); //prevent dead code eliminiation
    return new Date().getTime() - startTime;
};

var results = [];

for (var i = 0; i < 5; i = i + 1) {
    results.push(test());
}

for (var i = 0; i < results.length; i = i + 1) {
    console.log('Time needed: ' + results[i] + 'ms');
}

结果:

首次执行:

Time needed: 13654ms 
Time needed: 32192ms 
Time needed: 33167ms 
Time needed: 33587ms 
Time needed: 33630ms 

第二次执行:

Time needed: 14004ms 
Time needed: 32965ms 
Time needed: 33705ms 
Time needed: 33923ms 
Time needed: 33727ms 

第三次执行:

Time needed: 13124ms 
Time needed: 30706ms 
Time needed: 31555ms
Time needed: 32275ms
Time needed: 32752ms 

从第一排跳到第二排的原因是什么?

我的设置:

  • Ubuntu 13.10

  • Google Chrome 36.0.1985.125(Mozilla Firefox 30.0提供相同类型的结果)

编辑:

我修改了代码,在语义上保持相同但内联所有内容。有趣的是,它不仅显着加快了执行速度,而且还在很大程度上消除了我上面描述的现象。尽管如此,轻微的跳跃仍然是显而易见的。

修改后的代码:

http://jsfiddle.net/cay69/

结果:

首次执行:

Time needed: 13786ms 
Time needed: 14402ms 
Time needed: 14261ms 
Time needed: 14355ms 
Time needed: 14444ms 

第二次执行:

Time needed: 13778ms 
Time needed: 14293ms 
Time needed: 14236ms
Time needed: 14459ms 
Time needed: 14728ms 

第三次执行:

Time needed: 13639ms 
Time needed: 14375ms 
Time needed: 13824ms 
Time needed: 14125ms 
Time needed: 14081ms

3 个答案:

答案 0 :(得分:1)

经过一些测试后,我认为我已经指出可能导致差异的原因。它必须与类型我认为

有关
 var i,
     a = 0,
     startTime;

var a = 0为我提供了一个统一的结果,整体性能更快,另一方面var a = "0"给我的结果与你的相同:第一个有点快。

我不知道为什么会这样。

答案 1 :(得分:0)

Google Chrome似乎将您的脚本执行分解为块,并为其他进程提供处理时间。在每次函数调用执行大约600ms之前,它不会引人注意。我用较小的数据子集进行了测试(如果我没记错的话,可以测试300000000。)

答案 2 :(得分:0)

以下只是一个伪答案,我希望社区可以更新。最初,这将是一个评论,但它变得太冗长,太快,因此需要作为答案发布。


有趣/调查结果

running a few tests中,我无法找到与console.log使用的任何相关性。在OSX Safari中进行测试,我发现无论是否打印到控制台都存在问题。

我注意到的是一种模式。当我从你的初始起始值接近2147483648(2 ^ 31)时,有一个拐点。这很可能取决于用户的环境,但我发现了一个大约2147485000的拐点(尝试上面和下面的数字; 2147430000..2147490000)。在这个数字的某个地方,时间变得更加统一。

我真的希望它会是2 ^ 31 [确切],因为这个数字在计算机方面也很重要;它是long整数的上限。但是,我的测试得出的数字略高于此数(原因不明)。除了确保交换文件没有被使用之外,我没有做任何其他的内存分析。


来自提问者的编辑:

在我的设置中,它实际上正好是跳跃发生的2 ^ 31。我通过使用以下代码进行测试:

http://jsfiddle.net/8w24v/


此信息可能支持Derek的初始化观察。

这只是一个想法,可能是一个延伸:
LLVM或其他可能正在执行一些前期优化。也许循环变量以int开始,然后在一两次传递后,优化器注意到该变量变为long。在尝试优化时,它会尝试将其设置为前期长,仅在这种情况下,它不是节省时间的优化,因为使用常规整数的性能优于从int到long的转换成本。 / em>的

如果答案在ECMAScript文档中的某处,我不会感到惊讶:)