定位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;
答案 0 :(得分:4)
单个for循环中的多个语句,计数器递增最快
因此,考虑到这一点,您为不同的调用/语句多次运行循环。您可能会认为,如果将其置于单个for循环中并不重要,因为正在执行的操作数相同。如果你这么想,你错了!让我们分解一下:
i = 0
并读取检查i<500000
然后调用该函数或运行表达式然后增加计数器i++
499999
次,检查是否为i < 500000
,然后调用函数或运行表达式,并每次将计数器递增1。
499999
周期内的总操作次数: 3 operation each time x499999 = 1499997
i < 500000
是否返回false并打破循环。
第二个循环和其他循环遵循相同的过程,在这种情况下具有相同的数字步骤。 三个循环的操作总数: 1500002 x 3 = 4500006
第一次循环运行,它初始化计数器i = 0
并读取检查i<500000
然后运行表达式或调用函数在我们的情况下它的3函数用于第一个数组成员然后增加计数器{ {1}}
i++
是否返回false并打破循环。
单个循环的操作总数: 6 + 2499995 + 1 = 2500002
4500006 - 2500002 = 2000004
2000004更多操作!!!!!
i < 500000
并读取检查是否为i = 500000
,现在在函数运行之前,它首先将数组填充为具有500,000成员的空数组,然后调用该函数或运行表达式在我们的例子中,它的第一个数组成员的3函数然后增加计数器i>-1
所以在内部它运行499999次操作来创建空成员,然后在索引500000调用该函数或运行表达式。答案 1 :(得分:2)
我怀疑javascript中存在明显的逻辑上可解释的差异,但我们可以说它是C ++或类似的东西。在典型情况下,单循环会更快,但原因更隐蔽。三个循环值的影响很小,因为:
三个循环的最大问题是,整个数组必须被读取三次,如果它不适合缓存,则有缓存未命中。三个循环的数据位置较差,因此速度较慢。
另一方面,它取决于a1(),a2(),a3()是什么。如果这些操作如此之大以至于它们在某些内部数据结构上竞争高速缓存,那么这三个循环可能胜过单循环。但这不是典型的情况。
答案 2 :(得分:1)
单循环在本质上是更好的,因为当你到达那里时,你只需要在循环中完成3件事,然后你完成剩下的工作。在第一种情况下,你必须循环一次指令500000次,然后在下一次指令上循环500000次,依此类推。
答案 3 :(得分:1)
单循环会更快。
内部(a1
,a2
,a3
)内的操作在两个选项中都会执行相同的次数,但增加计数器的额外费用{ {1}}并检查它是否已达到限制。
当你进行3次循环时,这完成了500000 * 3 = 1.5M次,只需一次循环,它就完成了500000次。