ProgramingTip

const, let 및 var의 v8 JavaScript 성능 영향?

bestdevel 2020. 11. 21. 09:30
반응형

const, let 및 var의 v8 JavaScript 성능 영향?


기능적 차이에 관계없이 새 키워드 'let'및 'const'를 사용하면 '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


TL; DR

이론적 으로이 루프의 최적화되지 않은 버전 :

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

다음과 같은 루프의 최적화되지 않은 버전보다 느립니다 var.

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

때문에 다른 i 변수가 각각의 루프 반복에 대해 생성되고 let, 단지 하나에 반면있다 ivar.

실제로 2018 년에 V8은 루프를 충분히 검사하여 언제 그 차이를 최적화 할 수 있는지 알 수 있습니다. (그 전에도 루프가 충분한 작업을 수행하여 추가 let관련 오버 헤드가 제거 될 가능성이 있습니다 .하지만 이제는 걱정할 필요가 없습니다.)

세부

루프 에서 var사이의 중요한 차이점은 각 반복마다 다른 것이 생성 된다는 것입니다 . 고전적인 "루프의 폐쇄"문제를 해결합니다.letfori

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);

각 루프 본문 ( spec link )에 대한 새 EnvironmentRecord를 만드는 것은 작업이며 작업에는 시간이 걸리므로 이론적으로 let버전이 버전보다 느립니다 var.

그러나 i위의 실행 가능한 스 니펫 예제에서했던 것처럼를 사용하는 루프 내에서 함수 (클로저)를 만드는 경우에만 차이가 중요합니다 . 그렇지 않으면 구별을 관찰 할 수없고 최적화 할 수 있습니다.

여기 2018 년에는 V8 (및 Firefox의 SpiderMonkey)이의 let반복 당 변수 의미 체계를 사용하지 않는 루프에 성능 비용이 없다는 충분한 인트로 스펙 션을 수행하는 것처럼 보입니다 . 이 jsPerf 테스트를 참조하십시오 .


어떤 경우에는 특히 전역 변수에 대해 그렇지 않은 const최적화 기회를 제공 할 수 있습니다 var.

전역 변수의 문제는 그것이 전역 적이라는 것입니다. 어떤 코드 어디는 그것을 액세스 할 수 있습니다. 따라서 var변경할 의도가없고 코드를 변경하지 않는 변수를 선언 하면 엔진은 나중에로드 된 코드의 결과 또는 이와 유사한 결과로 변경되지 않을 것이라고 가정 할 수 없습니다.

const하지만, 명시 적으로 값이 change¹ 수없는 엔진을 말하는 것입니다. 따라서 값을 변경할 수 없다는 것을 알고 코드를 사용하는 코드에 대한 변수 참조 대신 리터럴을 내보내는 등 원하는 최적화를 수행 할 수 있습니다.

¹ 객체의 경우 값은 객체 자체가 아니라 객체에 대한 참조 임을 기억하십시오 . 따라서를 사용 const o = {}하면 객체 ( o.answer = 42) 의 상태를 변경할 수 있지만 o새 객체를 가리킬 수 없습니다 (포함 된 객체 참조를 변경해야하기 때문).


let또는 const다른 var유사한 상황 에서 사용할 때 성능이 다를 가능성이 없습니다. 이 함수는 var또는 을 사용하든 정확히 동일한 성능을 가져야 let합니다. 예를 들면 다음과 같습니다.

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

물론 해결해야 할 실제 문제가있는 경우에만 문제가되지 않으며 걱정해야 할 문제입니다.


루프 선언에서 "LET"가 더 좋습니다.

네비게이터에서 다음과 같은 간단한 테스트 (5 회)를 사용합니다.

// WITH VAR
console.time("var-time")
for(var i = 0; i < 500000; i++){}
console.timeEnd("var-time")

평균 실행 시간은 2.5ms 이상입니다.

// WITH LET
console.time("let-time")
for(let i = 0; i < 500000; i++){}
console.timeEnd("let-time")

평균 실행 시간은 1.5ms 이상입니다.

let을 사용한 루프 시간이 더 낫다는 것을 알았습니다.


TJ Crowder 의 대답은 너무 훌륭합니다.

여기에 다음이 추가되었습니다. "기존 var 선언을 const로 편집하는 데 드는 비용을 언제 가장 많이 얻을 수 있습니까?"

가장 큰 성능 향상은 "내 보낸"함수와 관련이 있다는 것을 알았습니다.

따라서 파일 A, B, R 및 Z가 앱을 통해 일반적으로 사용되는 파일 U의 "유틸리티"함수를 호출하는 경우 해당 유틸리티 함수를 "const"로 전환하면 const에 대한 상위 파일 참조가 약해질 수 있습니다. 성능이 향상되었습니다. 제게는 눈에 띌 정도로 빠르지는 않은 것 같았지만 전체 메모리 소비는 완전히 모 놀리 식인 프랑켄슈타인 앱의 경우 약 1-3 % 감소했습니다. 클라우드 또는 베어 메탈 서버에서 현금 가방을 사용하는 경우 이러한 var 선언 중 일부를 const로 업데이트하는 데 30 분을 소비하는 것이 좋은 이유가 될 수 있습니다.

나는 당신이 어떻게 const, var 및 let이 커버 아래에서 작동하는지 읽었다면 이미 위의 결론을 내렸을 것입니다. 그러나 당신이 그것을 "흘렀을 경우": D.

업데이트를 할 때 노드 v8.12.0에서 벤치마킹 한 것을 기억 해보면 내 앱은 ~ 240MB RAM의 유휴 소비량에서 ~ 233MB RAM으로 변경되었습니다.


TJ Crowder의 대답은 매우 좋지만 :

  1. 'let'은 코드를 더 강력하지 않고 더 읽기 쉽게 만들기 위해 만들어졌습니다.
  2. 이론적으로는 var보다 느릴 것입니다.
  3. 실제로 컴파일러는 완료되지 않은 프로그램을 완전히 (정적 분석) 해결할 수 없으므로 언젠가 최적화를 놓칠 수 있습니다.
  4. 어떤 경우에도 'let'을 사용하면 내부 검사를 위해 더 많은 CPU가 필요하며 Google v8이 파싱을 시작할 때 벤치를 시작해야합니다.
  5. 인트로 스펙 션이 실패하면 'let'은 V8 가비지 컬렉터를 강하게 밀고 해제 / 재사용하려면 더 많은 반복이 필요합니다. 또한 더 많은 RAM을 소비합니다. 벤치는 이러한 점을 고려해야합니다.
  6. Google Closure는 let in var를 변환합니다.

var와 let 사이의 성능 차이의 영향은 단일 기본 루프가 아닌 실제 전체 프로그램에서 볼 수 있습니다.

어쨌든 let을 사용할 필요가없는 곳에서 사용하면 코드를 읽을 수 없게됩니다.

참고 URL : https://stackoverflow.com/questions/40070631/v8-javascript-performance-implications-of-const-let-and-var

반응형