v8 const,let和var的JavaScript性能影响? [英] v8 JavaScript performance implications of const, let, and var?

查看:184
本文介绍了v8 const,let和var的JavaScript性能影响?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

无论功能差异如何,使用新关键字'let'和'const'是否会对相对于'var'的性能产生任何普遍或特定的影响?

Regardless of functional differences, does using the new keywords 'let' and 'const' have any generalized or specific impact on performance relative to 'var'?

之后运行程序:

function timeit(f, N, S) {
    var start, timeTaken;
    var stats = {min: 1e50, max: 0, N: 0, sum: 0, sqsum: 0};
    var i;
    for (i = 0; i < S; ++i) {
        start = Date.now();
        f(N);
        timeTaken = Date.now() - start;

        stats.min = Math.min(timeTaken, stats.min);
        stats.max = Math.max(timeTaken, stats.max);
        stats.sum += timeTaken;
        stats.sqsum += timeTaken * timeTaken;
        stats.N++
    }

    var mean = stats.sum / stats.N;
    var sqmean = stats.sqsum / stats.N;

    return {min: stats.min, max: stats.max, mean: mean, spread: Math.sqrt(sqmean - mean * mean)};
}

var variable1 = 10;
var variable2 = 10;
var variable3 = 10;
var variable4 = 10;
var variable5 = 10;
var variable6 = 10;
var variable7 = 10;
var variable8 = 10;
var variable9 = 10;
var variable10 = 10;

function varAccess(N) {
    var i, sum;
    for (i = 0; i < N; ++i) {
        sum += variable1;
        sum += variable2;
        sum += variable3;
        sum += variable4;
        sum += variable5;
        sum += variable6;
        sum += variable7;
        sum += variable8;
        sum += variable9;
        sum += variable10;
    }
    return sum;
}

const constant1 = 10;
const constant2 = 10;
const constant3 = 10;
const constant4 = 10;
const constant5 = 10;
const constant6 = 10;
const constant7 = 10;
const constant8 = 10;
const constant9 = 10;
const constant10 = 10;

function constAccess(N) {
    var i, sum;
    for (i = 0; i < N; ++i) {
        sum += constant1;
        sum += constant2;
        sum += constant3;
        sum += constant4;
        sum += constant5;
        sum += constant6;
        sum += constant7;
        sum += constant8;
        sum += constant9;
        sum += constant10;
    }
    return sum;
}


function control(N) {
    var i, sum;
    for (i = 0; i < N; ++i) {
        sum += 10;
        sum += 10;
        sum += 10;
        sum += 10;
        sum += 10;
        sum += 10;
        sum += 10;
        sum += 10;
        sum += 10;
        sum += 10;
    }
    return sum;
}

console.log("ctl = " + JSON.stringify(timeit(control, 10000000, 50)));
console.log("con = " + JSON.stringify(timeit(constAccess, 10000000, 50)));
console.log("var = " + JSON.stringify(timeit(varAccess, 10000000, 50)));

..我的结果如下:

ctl = {"min":101,"max":117,"mean":108.34,"spread":4.145407097016924}
con = {"min":107,"max":572,"mean":435.7,"spread":169.4998820058587}
var = {"min":103,"max":608,"mean":439.82,"spread":176.44417700791374}

然而,此处所述的讨论似乎表明在某些情况下性能差异的真正潜力: https://esdiscuss.org/topic/performance-concern-with-let-const

However discussion as noted here seems to indicate a real potential for performance differences under certain scenarios: https://esdiscuss.org/topic/performance-concern-with-let-const

推荐答案

TL; DR



理论上,这个循环的未经优化的版本:

TL;DR

In theory, an unoptimized version of this loop:

for (let i = 0; i < 500; ++i) {
    doSomethingWith(i);
}

将比使用<$ c $的同一循环的未优化版本慢c> var :

for (var i = 0; i < 500; ++i) {
    doSomethingWith(i);
}

因为不同 i 为每个循环迭代创建变量,使用 let ,而只有一个 i var

because a different i variable is created for each loop iteration with let, whereas there's only one i with var.

在实践中,在2018年,V8对内部进行了足够的反省循环知道何时可以优化差异。 (甚至在此之前,可能是你的循环正在做足够的工作,无论如何额外的相关的开销被淘汰。但现在你甚至不必担心它。)

In practice, here in 2018, V8 does enough introspection of the loop to know when it can optimize that difference away. (Even before then, odds are your loop was doing enough work that the additional let-related overhead was washed out anyway. But now you don't even have to worry about it.)

var 和让中的 for 循环是一个不同的 i 为每次迭代创建;它解决了经典的循环闭包问题:

The important difference between var and let in a for loop is that a different i is created for each iteration; it addresses the classic "closures in loop" problem:

function usingVar() {
  for (var i = 0; i < 3; ++i) {
    setTimeout(function() {
      console.log("var's i: " + i);
    }, 0);
  }
}
function usingLet() {
  for (let i = 0; i < 3; ++i) {
    setTimeout(function() {
      console.log("let's i: " + i);
    }, 0);
  }
}
usingVar();
setTimeout(usingLet, 20);

为每个循环体创建新的EnvironmentRecord(规范链接)是有效的,工作需要时间,这就是理论上版本慢于 var 版本的原因。

Creating the new EnvironmentRecord for each loop body (spec link) is work, and work takes time, which is why in theory the let version is slower than the var version.

但是,如果你在使用 i 的循环中创建一个函数(闭包),差别才有意义,正如我在上面的runnable片段示例中所做的那样。否则,无法观察到这种区别,并且可以对其进行优化。

But the difference only matters if you create a function (closure) within the loop that uses i, as I did in that runnable snippet example above. Otherwise, the distinction can't be observed and can be optimized away.

在2018年,它看起来像V8(和Firefox中的SpiderMonkey)正在做足够的内省,在没有使用 let 的每次迭代变量语义的循环中没有性能成本。请参阅此jsPerf测试

Here in 2018, it looks like V8 (and SpiderMonkey in Firefox) is doing sufficient introspection that there's no performance cost in a loop that doesn't make use of let's variable-per-iteration semantics. See this jsPerf test.

在某些情况下, const 可能会提供优化的机会 var 不会,特别是对于全局变量。

In some cases, const may well provide an opportunity for optimization that var wouldn't, especially for global variables.

全局变量的问题在于它是全局的; 任何代码 可以访问它。因此,如果您使用 var 声明一个您永远不打算更改的变量(并且永远不会对您的代码进行更改),那么引擎就不能假设它永远不会改变为以后加载的代码或类似的结果。

The problem with a global variable is that it's, well, global; any code anywhere could access it. So if you declare a variable with var that you never intend to change (and never do change in your code), the engine can't assume it's never going to change as the result of code loaded later or similar.

但是,使用 const ,你明确地告诉引擎价值不能改变¹。因此可以自由地进行任何所需的优化,包括使用它发出文字而不是代码的变量引用,知道值无法更改。

With const, though, you're explicitly telling the engine that the value cannot change¹. So it's free to do any optimization it wants, including emitting a literal instead of a variable reference to code using it, knowing that the values cannot be changed.

¹请记住,对于对象,值是对象的引用,而不是对象本身。因此,使用 const o = {} ,您可以更改对象的状态( o.answer = 42 ),但是你不能让 o 指向一个新对象(因为这需要更改它包含的对象引用)。​​

¹ Remember that with objects, the value is a reference to the object, not the object itself. So with const o = {}, you could change the state of the object (o.answer = 42), but you can't make o point to a new object (because that would require changing the object reference it contains).

当使用时,让 const 进入其他 var 类似的情况,他们不太可能有不同的表现。无论您使用 var 还是 let ,此函数应具有完全相同的性能,例如:

When using let or const in other var-like situations, they're not likely to have different performance. This function should have exactly the same performance whether you use var or let, for instance:

function foo() {
    var i = 0;
    while (Math.random() < 0.5) {
        ++i;
    }
    return i;
}






当然,这一切都是当然的,只有当有一个真正的问题需要解决时,不太重要,有些事情需要担心。


It's all, of course, unlikely to matter and something to worry about only if and when there's a real problem to solve.

这篇关于v8 const,let和var的JavaScript性能影响?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆