性能:具有多个语句的单循环或具有单个调用的多个循环

时间:2017-03-11 13:28:30

标签: javascript performance

定位Javascript,其中哪些应该快?

使用单个语句的多个循环:

var array = [];
for(var i = 0; i < 500000; i++) {
    a1();
}
for(var i = 0; i < 500000; i++) {
    a2();
}
for(var i = 0; i < 500000; i++) {
    a3();
}

或包含多个语句的单循环:

var array = [];
for(var i = 0; i < 500000; i++) {
    a1();
    a2();
    a3();
}

为了尝试理解它,我在jsperf.com上运行它。请在此处查看:https://jsperf.com/loops-or-calls/1。但是,从理论上讲,哪个应该具有最佳性能? 为什么?

编辑1:我不知道为什么,但按逆序运行会更改操作/秒: 多个语句的性能比多个循环差。 https://jsperf.com/loops-or-calls/1

编辑2:我认为它没有任何区别,因为:5k次x 3 ops = 15k。否则:5k(第一次循环)+ 5k(第二次循环)+ 5k(第三次循环)=相同的15k;

4 个答案:

答案 0 :(得分:4)

我的回答

单个for循环中的多个语句,计数器递增最快

逻辑解释

对于多个循环:

因此,考虑到这一点,您为不同的调用/语句多次运行循环。您可能会认为,如果将其置于单个for循环中并不重要,因为正在执行的操作数相同。如果你这么想,你错了!让我们分解一下:

First Loop

  • 第一次第一次循环运行,它初始化计数器i = 0并读取检查i<500000然后调用该函数或运行表达式然后增加计数器i++
    • 操作次数: 4
  • 休息499999次,检查是否为i < 500000,然后调用函数或运行表达式,并每次将计数器递增1。
    • 499999周期内的总操作次数: 3 operation each time x499999 = 1499997
  • 最后一次检查i < 500000是否返回false并打破循环。
    • 操作次数: 1

第一次循环的总操作次数:

4 + 1499997 + 1 = 1500002

其他循环

  • 第二个循环和其他循环遵循相同的过程,在这种情况下具有相同的数字步骤。 三个循环的操作总数: 1500002 x 3 = 4500006

    对于带有多个语句/调用的单循环:

  • 第一次循环运行,它初始化计数器i = 0并读取检查i<500000然后运行表达式或调用函数在我们的情况下它的3函数用于第一个数组成员然后增加计数器{ {1}}

    • 操作次数 6次操作
  • 休息499,999次,它检查条件,并运行表达式或调用函数并增加计数器
    • 操作次数:每周期5次操作= 5 x 499999 = 2499995操作
  • 最后一次检查i++是否返回false并打破循环。
    • 操作次数: 1

单个循环的操作总数: 6 + 2499995 + 1 = 2500002

内部执行的操作数量的差异

  

4500006 - 2500002 = 2000004

    2000004更多操作!!!!!

为什么递减循环缓慢!

  • 第一次循环运行,它初始化计数器i < 500000并读取检查是否为i = 500000,现在在函数运行之前,它首先将数组填充为具有500,000成员的空数组,然后调用该函数或运行表达式在我们的例子中,它的第一个数组成员的3函数然后增加计数器i>-1 所以在内部它运行499999次操作来创建空成员,然后在索引500000调用该函数或运行表达式。

答案 1 :(得分:2)

我怀疑javascript中存在明显的逻辑上可解释的差异,但我们可以说它是C ++或类似的东西。在典型情况下,单循环会更快,但原因更隐蔽。三个循环值的影响很小,因为:

  • 递增很快
  • 条件是假的99,999%的时间很快(可以预测)
  • 循环可以展开

三个循环的最大问题是,整个数组必须被读取三次,如果它不适合缓存,则有缓存未命中。三个循环的数据位置较差,因此速度较慢。

另一方面,它取决于a1(),a2(),a3()是什么。如果这些操作如此之大以至于它们在某些内部数据结构上竞争高速缓存,那么这三个循环可能胜过单循环。但这不是典型的情况。

答案 2 :(得分:1)

单循环在本质上是更好的,因为当你到达那里时,你只需要在循环中完成3件事,然后你完成剩下的工作。在第一种情况下,你必须循环一次指令500000次,然后在下一次指令上循环500000次,依此类推。

答案 3 :(得分:1)

单循环会更快。

内部(a1a2a3)内的操作在两个选项中都会执行相同的次数,但增加计数器的额外费用{ {1}}并检查它是否已达到限制。

当你进行3次循环时,这完成了500000 * 3 = 1.5M次,只需一次循环,它就完成了500000次。