Javascript临时死区NodeJS 7.9.0性能下降?

mit*_*1os 5 javascript variable-declaration node.js ecmascript-6

我在另一个问题中注意到使用letvar变量声明时循环的性能差异.

最初的问题是正确回答,letfor循环中使用较慢,因为let为每次迭代创建一个新的作用域来保存let声明的变量的值.还有更多工作要做,所以慢一点是正常的.作为参考,我在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');
Run Code Online (Sandbox Code Playgroud)

输出:

var: 55.792ms
let: 247.123ms
Run Code Online (Sandbox Code Playgroud)

为了避免j在循环的每次迭代中额外的范围声明,我们j在循环之前声明变量.人们可能会认为这应该使let循环性能与之匹配var.但不是!!!这是代码和结果供参考:

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');
Run Code Online (Sandbox Code Playgroud)

输出:

var: 231.249ms
let: 233.485ms
Run Code Online (Sandbox Code Playgroud)

我们可以看到,不仅let循环没有得到更快,而且var循环变得和那个一样慢let!对此的唯一解释是,由于我们不在任何块或函数中,因此两个变量都在全局模块范围内声明.然而,由于引用这里时,let在范围的中间变量声明,创建了一个时间盲区,这让变量j初始化,而var定义的初始化变量.

因此,虽然未引用未初始化的变量,但在时间死区中运行代码必须非常慢....

最后为了显示顺序,我们j在程序顶部声明变量,以显示在没有时间死区的情况下运行它的结果.

没有临时死区的代码:

'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');
Run Code Online (Sandbox Code Playgroud)

输出:

var: 55.586ms
let: 55.009ms
Run Code Online (Sandbox Code Playgroud)

现在两个letvar循环都有类似的优化性能!

有谁知道我关于时间死区性能的假设是否正确,还是提供了不同的解释?

rsp*_*rsp 2

这是在多个 Node 版本上进行测试的输出:

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
Run Code Online (Sandbox Code Playgroud)

这些并不是所有的 Node 版本,只是我在本地安装的版本,因此很容易测试。

显然,大多数版本的行为都是一致的:放在let循环之外会使速度稍微快一些,但会使var其他地方慢得多。

6.5.0 中似乎发生了一些不好的事情,但在 7.x 中已修复。

它可以留出一些优化空间,但我不会太担心var速度变慢。我对制作得更快更感兴趣let

将这些示例放入函数中并让它们运行多次可以让 JIT 启动并优化函数,因此结果可能与第一次运行所有内容时看到的结果不同。