繁体   English   中英

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

[英]JavaScript - Are loops faster than discretely writing line-by-line?

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

这个:

for(var i = 0; i < 10; i++){
  --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--
--do that thing--

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

通过反复“复制粘贴及”循环体“展开”循环可以提高或降低性能。

结果取决于......

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

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

普通循环:

var count = 0;
for (var i = 0; i < 10; i++) {
  count += 1;
}

展开循环:

var count = 0;
count += 1;
count += 1;
... 
count += 1;

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

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

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

普通循环:

function f() {
  return 1;
}

var count = 0;
for (var i = 0; i < 10; i++) {
  count += f();
}

展开循环:

var count = 0;
count += f();
count += f();
... 
count += f();

结果:展开的循环速度提高了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;
}

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

这是为什么?

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

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

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

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

这取决于您正在使用的JS引擎。 循环展开是一种常见的优化技术,可以在没有您干预的情况下使用,因此它实际上取决于您的代码被解释的引擎。

通常,您可以使用http://jsperf.com/来测试不同浏览器中性能差异的特定代码,但似乎已经停机了几天进行维护。 相反,您可以手动将每个选择的代码放在他们自己的函数中,在测试开始时存储时间,调用函数10,000次或者其他东西,然后记录经过的时间。 这是一个例子:

  function testEmpty(){ } function testLoop(){ for(var i = 0; i < 10; i++){void i;} } function testUnrolled(){ void 0;void 1;void 2;void 3;void 4;void 5;void 6;void 7;void 8;void 9; } function testLoop2(){ for(var i = 0; i < 10; i++){void Date();} } function testUnrolled2(){ void Date();void Date();void Date();void Date();void Date(); void Date();void Date();void Date();void Date();void Date(); } function testFunction(func, num){ var a=Date.now(); for(var i=0;i<num;i++){ func(); } return Date.now() - a; } console.log(testFunction(testEmpty,10000000)); // Took 9ms console.log(testFunction(testLoop,10000000)); // Took 112ms console.log(testFunction(testUnrolled,10000000)); // Took 42ms console.log(testFunction(testLoop2,10000)); // Took 705ms console.log(testFunction(testUnrolled2,10000)); // Took 714ms 

保持浏览器不变(Firefox 47),这实际上表明性能变化与一种编码风格无关。 事实上,取决于重复的内容会产生影响。

总的来说,将循环递增到10会产生完全不明显的性能影响,因此通常差异可以忽略不计(性能可能不应该考虑使用哪种样式)。

如果它只是简单的计算语句,则第二个版本更快。

但是,当你可以循环它时,为什么要使代码变得如此丑陋且难以理解(它取决于每行的语句)。

在另一方面,代码将被优化,你不会感觉到差异。

还要记住它是JS。 所以在某些情况下,语句可以是异步的,无需顺序运行(无需等待前一个语句的结束)。

程序员不是代码循环机,程序员必须编写一次并享受自动化。

哪个脚本会更快完成

对此没有唯一有效的答案。

其他答案推测假设。

该标准并不保证其中任何一个更快/更慢,因此人们只能在给定的机器上运行给定的ES实现,并且仅在它们测量之后。 但要注意,在微基准测试之后得到任何合理的数字是很难的(大多数基准产生一些数字而不是必需的那些数字意味着什么)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM