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
, 단지 하나에 반면있다 i
와 var
.
실제로 2018 년에 V8은 루프를 충분히 검사하여 언제 그 차이를 최적화 할 수 있는지 알 수 있습니다. (그 전에도 루프가 충분한 작업을 수행하여 추가 let
관련 오버 헤드가 제거 될 가능성이 있습니다 .하지만 이제는 걱정할 필요가 없습니다.)
세부
루프 에서 var
와 사이의 중요한 차이점은 각 반복마다 다른 것이 생성 된다는 것입니다 . 고전적인 "루프의 폐쇄"문제를 해결합니다.let
for
i
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의 대답은 매우 좋지만 :
- 'let'은 코드를 더 강력하지 않고 더 읽기 쉽게 만들기 위해 만들어졌습니다.
- 이론적으로는 var보다 느릴 것입니다.
- 실제로 컴파일러는 완료되지 않은 프로그램을 완전히 (정적 분석) 해결할 수 없으므로 언젠가 최적화를 놓칠 수 있습니다.
- 어떤 경우에도 'let'을 사용하면 내부 검사를 위해 더 많은 CPU가 필요하며 Google v8이 파싱을 시작할 때 벤치를 시작해야합니다.
- 인트로 스펙 션이 실패하면 'let'은 V8 가비지 컬렉터를 강하게 밀고 해제 / 재사용하려면 더 많은 반복이 필요합니다. 또한 더 많은 RAM을 소비합니다. 벤치는 이러한 점을 고려해야합니다.
- Google Closure는 let in var를 변환합니다.
var와 let 사이의 성능 차이의 영향은 단일 기본 루프가 아닌 실제 전체 프로그램에서 볼 수 있습니다.
어쨌든 let을 사용할 필요가없는 곳에서 사용하면 코드를 읽을 수 없게됩니다.
'ProgramingTip' 카테고리의 다른 글
java.lang.NumberFormatException을 어떻게해야합니까? 입력의 경우 :“N / A”? (0) | 2020.11.21 |
---|---|
.map () 자바 펼쳐 ES6 맵? (0) | 2020.11.21 |
이벤트 처리기를 등록 취소하는 방법 (0) | 2020.11.21 |
NULL을 허용하는 MySQL 외래 키? (0) | 2020.11.21 |
취소하지 않는 것이 나쁜가요? (0) | 2020.11.21 |