JavaScript临时死区NodeJS 7.9.0性能下降?
我在其他问题中注意到使用let
和var
variables声明时循环中的性能差异。
最初的问题是正确的回答,使用let
for循环比较慢,因为let
为每个迭代创build一个新的范围来保存let
声明variables的值。 更多的工作要做,所以慢一点是正常的。 就像参考一样,我给出了代码和NodeJS(7.9.0)执行时间的结果:
请注意下面的所有javascript代码都是关于NodeJS版本7.9.0的
常规代码:
'use strict'; console.time('var'); for (var i = 0; i < 100000000; i++) {} console.timeEnd('var'); console.time('let'); for (let j = 0; j < 100000000; j++) {} console.timeEnd('let');
输出:
var: 55.792ms let: 247.123ms
为了避免在循环的每次迭代中对j
额外的范围声明,我们在循环之前声明j
variables。 人们会期望,现在应该let
循环的性能匹配variables之一。 但不是!!! 这是代码和结果供参考:
在循环之前使用let
定义的代码:
'use strict'; console.time('var'); for (var i = 0; i < 100000000; i++) {} console.timeEnd('var'); console.time('let'); let j; for (j = 0; j < 100000000; j++) {} console.timeEnd('let');
输出:
var: 231.249ms let: 233.485ms
我们可以看到,不仅let
循环没有得到任何更快的速度,而且var
循环变得和let
循环一样慢! 唯一的解释是,由于我们不在任何块或函数中,所以这两个variables都在全局模块范围内声明。 然而,正如这里所引用的那样,在范围中间的variables的let
声明创build了一个暂时的死区 ,它使得variablesj
初始化,而var
则按照定义初始化variables。
因此,在未经初始化的variables未被引用的情况下,在时间死区运行代码必须相当慢。
最后为了表示尊重,我们在程序的顶部声明了j
variables,以显示运行它的结果,没有时间死区 。
没有时间死区的代码:
'use strict'; let j; console.time('var'); for (var i = 0; i < 100000000; i++) {} console.timeEnd('var'); console.time('let'); for (j = 0; j < 100000000; j++) {} console.timeEnd('let');
输出:
var: 55.586ms let: 55.009ms
现在let
和var
循环都有类似的优化性能!
有没有人知道我对于时间死区性能的假设是否正确,或提供不同的解释?
这是几个Node版本的testing输出:
node-v4.0.0 var: 92ms let: 336ms var: 220ms let: 230ms ===== node-v4.2.2 var: 95ms let: 342ms var: 228ms let: 233ms ===== node-v5.1.0 var: 93.418ms let: 342.050ms var: 264.895ms let: 228.310ms ===== node-v5.12.0 var: 103.254ms let: 340.990ms var: 228.698ms let: 228.213ms ===== node-v6.3.1 var: 109.476ms let: 338.127ms var: 232.381ms let: 241.795ms ===== node-v6.5.0 var: 96.630ms let: 339.570ms var: 686.631ms let: 612.820ms ===== node-v6.7.0 var: 106.760ms let: 349.677ms var: 690.753ms let: 587.444ms ===== node-v7.0.0 var: 95.366ms let: 333.880ms var: 222.668ms let: 234.101ms ===== node-v7.4.0 var: 101.074ms let: 330.778ms var: 221.869ms let: 238.053ms ===== node-v7.8.0 var: 93.604ms let: 338.447ms var: 224.263ms let: 233.313ms ===== node-v7.9.0 var: 92.622ms let: 333.552ms var: 275.980ms let: 230.990ms
这些并不是所有的Node版本,只是我在本地安装的版本,所以很容易testing。
显然这个行为在大多数版本中都是一致的:放在循环之外让它稍微快一些,但是使得var
其他地方慢得多。
似乎6.5.0中发生了一些不好的事情,但它是固定的7.x。
它可以留下一些优化的地方,但我不会太担心var
越来越慢。 我会更快地let
更感兴趣。
让这些例子变成函数并让它们运行几次可以使JIT启动并优化函数,因此结果可能会与第一次运行时看到的结果不同。