在JavaScript模式Stoyan Stefanov一书中,他声称在JavaScript中循环的常用方法
for (i = 0, max = myarray.length; i < max; i++) {
// do something with myarray[i]
}
可以通过使用此模式进行优化
for (i = myarray.length; i--;) {
// do something with myarray[i]
}
我发现这很有趣所以我决定在现实世界中通过将该技术应用于this blog post about doing pixel manipulation with canvas中显示的性能密集型循环来测试它。可以看到将常规代码与“优化”代码进行比较的基准here。
有趣的是,假设优化的循环实际上比Opera和Firefox中的常规循环方式慢。那是为什么?
答案 0 :(得分:3)
这种微优化的有效性总是非常有限。有可能VM实现包括对“通用方式”的优化,这些方式超出了您在语言级别所能做的事情。
这就是为什么微优化通常是浪费时间的原因。初学者倾向于对它们着迷并最终编写难以维护且速度慢的代码。
答案 1 :(得分:1)
首先,我认为没有理由认为第二个应该比第一个快得多。与零比较与与另一个数字进行比较之间的差异可能会对编译代码中的极其紧密的循环产生影响,但即便如此,大多数情况下也可能存在货币崇拜(如果你有理查德费曼的Cargo Cult Science没有得到参考,如果没有别的它是一个很好的阅读,也有不止一些类似的倾向复制一些运作良好的东西到一个没有真正理由认为它将有助于编程的情况下)
我可以看到以下情况变慢:
for (i = 0; i < myarray.length; i++) {
// do something with myarray[i]
}
但是我也可以看到它不更慢,如果引擎为你提升了长度检查的优化,或者实现是这样的,检查长度和检查变量大致相当无论如何都要付出代价。
我还可以看到你或者给出的第一个代码示例,或者两者都是给定脚本引擎优化的东西 - 它毕竟是js中非常常见的习惯用法,并且本质上涉及循环,所以它会尝试在脚本引擎中检测和优化是一个明智的事情。
除了这些猜想之外,我们无法真正说出这一点,因为“因为一个引擎在另一个引擎上运行得更好,这就是为什么”没有达到javascript以下的水平并检查引擎的实现。你的结果会表明每个引擎的答案都不一样(毕竟,一个引擎的确与你的预期相符)。
现在,值得注意的是,无论如何,每种情况下结果都非常接近。如果您发现目前只有一两个浏览器在变化确实优化的情况下相当受欢迎,那么它仍然值得。
如果你对它是否有价值感兴趣,或者只是一个假设,你可以尝试获得Netscape 2的副本(毕竟有史以来第一个javascript浏览器),并运行一些代码测试它的方法。
编辑:如果你确实尝试了那种实验,另一种是尝试故意错误的循环,超过数组边界一个。引擎的一个可能的优化是实现你在走阵列,并检查一下你将在哪里结束超出范围。如果是这样,如果你最终会出错,你可能会有不同的结果。
答案 2 :(得分:1)
尝试优化循环的大多数方法来自C,而编译器更简单,处理器一个接一个地执行一个指令。
现代处理器以非常不同的方式运行代码,因此优化特定指令现在不具有相同的效果。
对于Javascript,现在变化非常快。它已经从被解释为编译,这产生了巨大的性能差异。编译器在浏览器之间是非常不同的,并且它们随着每个新的浏览器版本而变化,所以今天在一个浏览器中更快的东西明天可能会更慢。
我已经测试了一些优化循环的不同方法,目前性能差异很小:http://jsperf.com/loopoptimisations
但可以肯定的是,编写循环的常规方法是最常见的,因此所有编译器都将专注于优化。