JavaScript - 循环比逐行离散写入更快吗?

use*_*495 5 javascript performance loops readability

忽略所有代码清洁度和可读性,哪个脚本会更快完成?

这个:

for(var i = 0; i < 10; i++){
  --do that thing--
}
Run Code Online (Sandbox Code Playgroud)

或这个:

--do that thing--
--do that thing--
--do that thing--
--do that thing--
--do that thing--
--do that thing--
--do that thing--
--do that thing--
--do that thing--
--do that thing--
Run Code Online (Sandbox Code Playgroud)

或者它们是相同的,性能方面的?

le_*_*e_m 7

"展开"反复循环"复制粘贴及"循环体可以提高或降低性能.

结果取决于......

  • ......你的JavaScript引擎
  • ...循环体中的代码
  • ...你的代码记录得如何(不开玩笑!)

让我们使用Google流行的V8 JavaScript引擎(Chrome,Node)分析性能:

普通循环:

var count = 0;
for (var i = 0; i < 10; i++) {
  count += 1;
}
Run Code Online (Sandbox Code Playgroud)

展开循环:

var count = 0;
count += 1;
count += 1;
... 
count += 1;
Run Code Online (Sandbox Code Playgroud)

结果:展开的循环速度提高了10倍.

但是如果我们循环1000次而不是10次呢?然后展开的循环突然变得比普通循环慢10倍!

如果我们将简单的算术表达式与函数调用交换怎么办?

普通循环:

function f() {
  return 1;
}

var count = 0;
for (var i = 0; i < 10; i++) {
  count += f();
}
Run Code Online (Sandbox Code Playgroud)

展开循环:

var count = 0;
count += f();
count += f();
... 
count += f();
Run Code Online (Sandbox Code Playgroud)

结果:展开的循环速度提高了50%.

但是如果我们在函数f中添加注释呢?

function f() {
  // bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
  return 1;
}
Run Code Online (Sandbox Code Playgroud)

突然,展开的循环慢了20%!

这是为什么?

  • 在解析主体包含少于600个字符的函数(包括空格和注释)时,V8会自动内联代码.
  • 当函数在很长的循环中"卡住"时,V8执行堆栈替换.

关于最后一个例子:通过添加长> 600个字符的注释,我们阻止V8在解析期间内联函数f并依赖于运行时优化功能(例如'on stack replacement'),它针对整个函数和循环而不是手动重复代码.

正如您所看到的,很难预测这种微观"优化"的结果.所以最好不要这样做 - 除非你针对特定JS引擎的特定版本.

有关性能分析,请参阅https://jsfiddle.net/Lj9v7c2m/ - 根据您的计算机/浏览器/版本,您可能会得到不同的结果.