为啥在 for 循环之后比 for 循环之前慢得多?
Posted
技术标签:
【中文标题】为啥在 for 循环之后比 for 循环之前慢得多?【英文标题】:Why is let much slower after a for loop than before a for loop?为什么在 for 循环之后比 for 循环之前慢得多? 【发布时间】:2017-01-29 03:15:25 【问题描述】:在 node.js v6.0.0 中
function testlet()
let a = 0;
for (var i = 0; i < 100000000; i++)
function testlet2()
for (var i = 0; i < 100000000; i++)
let a = 0;
console.time('let');
testlet();
console.timeEnd('let');
console.time('let2');
testlet2();
console.timeEnd('let2');
let
在代码中的位置怎么会造成这么大的性能差异?
【问题讨论】:
在 chrome 中效果相同(不出意外) - 在其他浏览器中没有这种差异const
也会发生这种情况,但var
两者的速度相同。
虽然很奇怪,但我建议不要太担心它。微优化是一个移动的目标。今天快的东西明天很容易变慢。
测试下:node.js和chrome浏览器性能不同,firefox一样,比v8快。 safari 不支持 let
你能发布你得到的结果吗?
【参考方案1】:
我会做出有根据的猜测,并说temporal dead zone 是罪魁祸首。
那个循环,这似乎是你的微基准测试的内容,是eaten by the optimiser for breakfast,就像 Vyacheslav Egorov likes to put it 在他的谈话中一样。即使不是这样,引擎也会将变量递增一百万次,这两个函数的时间都相同。
不同的是创建变量a
的时间。在您的第一个 sn-p 中,它位于函数的开头,之前没有任何内容。没有时间死区,它本质上是一个函数范围的变量;将其更改为 var
不会有什么不同(试试看)。因此,当调用该函数时,将创建具有变量的范围并将值初始化为0
,然后运行(或不运行)一些代码。
相反,在第二个 sn-p 中有一个时间死区。在let
声明之前的代码中,访问a
必须抛出异常。因此,当调用该函数时,将创建范围并为a
保留一个插槽,但未初始化。在这种状态下,代码运行(或不运行),只有在此之后,变量才会被初始化并赋值为0
。
因此,如果let
位于代码中间(或代码之后),则作用域会更加复杂。这可能会导致优化器对其进行不同的处理,甚至可能会影响同一范围内的变量i
,或者可能根本无法进行某些优化。
【讨论】:
以上是关于为啥在 for 循环之后比 for 循环之前慢得多?的主要内容,如果未能解决你的问题,请参考以下文章
为啥以下简单的并行化代码比 Python 中的简单循环慢得多?
arrayfun 可能比 matlab 中的显式循环慢得多。为啥?