【问题标题】: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
  • 你能发布你得到的结果吗?

标签: javascript node.js 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,或者可能根本无法进行某些优化。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-29
    • 2014-01-21
    • 2017-11-09
    • 2019-12-08
    • 2021-10-01
    • 2019-04-21
    相关资源
    最近更新 更多