Terlepas dari perbedaan fungsional, apakah menggunakan kata kunci baru 'let' dan 'const' memiliki dampak umum atau spesifik pada kinerja yang terkait dengan 'var'?
Setelah menjalankan program:
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)));
.. Hasil saya adalah sebagai berikut:
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}
Namun diskusi seperti yang disebutkan di sini tampaknya menunjukkan potensi nyata untuk perbedaan kinerja dalam skenario tertentu: https://esdiscuss.org/topic/performance-concern-with-let-const
javascript
performance
constants
v8
let
sean2078
sumber
sumber
let
digunakan dalam lingkup blok harus lebih berkinerja daripadavar
, yang tidak memiliki lingkup blok, tetapi hanya lingkup fungsi.let
akan melakukannya, dan kemudian sampah dikumpulkan, sementaravar
, yang merupakan cakupan fungsi, tidak akan bekerja dengan cara yang sama. Sekali lagi saya pikir, ini sangat spesifik untuk penggunaan, sehingga keduanyalet
danconst
bisa lebih berkinerja, tetapi tidak selalu demikian.var
danlet
: Tidak pernah digunakanlet
sama sekali.Jawaban:
TL; DR
Secara teori , versi loop ini yang tidak dioptimalkan:
for (let i = 0; i < 500; ++i) { doSomethingWith(i); }
mungkin lebih lambat daripada versi yang tidak dioptimalkan dari loop yang sama dengan
var
:for (var i = 0; i < 500; ++i) { doSomethingWith(i); }
karena variabel yang berbeda
i
dibuat untuk setiap iterasi pengulangan denganlet
, sedangkan hanya ada satui
denganvar
.Memperdebatkan hal itu adalah fakta bahwa
var
hoisted sehingga dinyatakan di luar loop sedangkanlet
hanya dideklarasikan dalam loop, yang mungkin menawarkan keuntungan pengoptimalan.Dalam praktiknya , di tahun 2018 ini, mesin JavaScript modern melakukan introspeksi loop yang cukup untuk mengetahui kapan dapat mengoptimalkan perbedaan itu. (Bahkan sebelum itu, kemungkinan besar loop Anda telah melakukan pekerjaan yang cukup sehingga
let
overhead terkait tambahan telah hilang. Tetapi sekarang Anda bahkan tidak perlu khawatir tentang itu.)Berhati-hatilah dengan benchmark sintetis karena sangat mudah membuat kesalahan, dan memicu pengoptimalan mesin JavaScript dengan cara yang tidak dilakukan oleh kode asli (baik dan buruk). Namun, jika Anda menginginkan tolok ukur sintetis, berikut ini:
Tampilkan cuplikan kode
const now = typeof performance === "object" && performance.now ? performance.now.bind(performance) : Date.now.bind(Date); const btn = document.getElementById("btn"); btn.addEventListener("click", function() { btn.disabled = true; runTest(); }); const maxTests = 100; const loopLimit = 50000000; const expectedX = 1249999975000000; function runTest(index = 1, results = {usingVar: 0, usingLet: 0}) { console.log(`Running Test #${index} of ${maxTests}`); setTimeout(() => { const varTime = usingVar(); const letTime = usingLet(); results.usingVar += varTime; results.usingLet += letTime; console.log(`Test ${index}: var = ${varTime}ms, let = ${letTime}ms`); ++index; if (index <= maxTests) { setTimeout(() => runTest(index, results), 0); } else { console.log(`Average time with var: ${(results.usingVar / maxTests).toFixed(2)}ms`); console.log(`Average time with let: ${(results.usingLet / maxTests).toFixed(2)}ms`); btn.disabled = false; } }, 0); } function usingVar() { const start = now(); let x = 0; for (var i = 0; i < loopLimit; i++) { x += i; } if (x !== expectedX) { throw new Error("Error in test"); } return now() - start; } function usingLet() { const start = now(); let x = 0; for (let i = 0; i < loopLimit; i++) { x += i; } if (x !== expectedX) { throw new Error("Error in test"); } return now() - start; }
<input id="btn" type="button" value="Start">
Dikatakan bahwa tidak ada perbedaan yang signifikan dalam pengujian sintetik pada V8 / Chrome atau SpiderMonkey / Firefox. (Pengujian berulang di kedua browser memiliki satu pemenang, atau yang lainnya menang, dan dalam kedua kasus berada dalam margin kesalahan.) Namun sekali lagi, ini adalah tolok ukur sintetis, bukan kode Anda. Khawatir tentang kinerja kode Anda ketika dan jika kode Anda memiliki masalah kinerja.
Sebagai masalah gaya, saya lebih suka
let
untuk manfaat pelingkupan dan manfaat closure-in-loop jika saya menggunakan variabel loop dalam sebuah closure.Detail
Perbedaan penting antara
var
danlet
dalam sebuahfor
loop adalah perbedaani
yang dibuat untuk setiap iterasi; itu mengatasi masalah klasik "closures in loop":Tampilkan cuplikan kode
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);
Membuat EnvironmentRecord baru untuk setiap badan loop ( tautan spesifikasi ) adalah pekerjaan, dan pekerjaan membutuhkan waktu, itulah sebabnya secara teori
let
versinya lebih lambat daripadavar
versinya.Tetapi perbedaannya hanya penting jika Anda membuat fungsi (penutupan) di dalam loop yang menggunakan
i
, seperti yang saya lakukan dalam contoh cuplikan runnable di atas. Jika tidak, perbedaan tidak dapat diamati dan dapat dioptimalkan.Di sini, di tahun 2018, sepertinya V8 (dan SpiderMonkey di Firefox) melakukan introspeksi yang cukup sehingga tidak ada biaya kinerja dalam loop yang tidak menggunakan
let
semantik variabel per iterasi. Lihat tes ini .Dalam beberapa kasus,
const
mungkin juga memberikan peluang untuk pengoptimalan ituvar
tidak, terutama untuk variabel global.Masalah dengan variabel global adalah global; kode apa pun di mana pun dapat mengaksesnya. Jadi jika Anda mendeklarasikan variabel
var
yang tidak pernah ingin Anda ubah (dan tidak pernah melakukan perubahan dalam kode Anda), mesin tidak dapat berasumsi bahwa variabel tersebut tidak akan pernah berubah sebagai hasil dari kode yang dimuat nanti atau serupa.Dengan
const
, meskipun, Anda secara eksplisit mengatakan mesin yang nilai tidak dapat change¹. Jadi bebas melakukan pengoptimalan apa pun yang diinginkan, termasuk memancarkan literal alih-alih referensi variabel ke kode yang menggunakannya, mengetahui bahwa nilainya tidak dapat diubah.¹ Ingatlah bahwa dengan objek, nilainya adalah referensi ke objek, bukan objek itu sendiri. Jadi dengan
const o = {}
, Anda bisa mengubah status object (o.answer = 42
), tetapi Anda tidak bisao
menunjuk ke objek baru (karena itu akan memerlukan perubahan referensi objek yang dikandungnya).Saat menggunakan
let
atauconst
dalamvar
situasi serupa lainnya , mereka cenderung tidak memiliki kinerja yang berbeda. Fungsi ini harus memiliki kinerja yang persis sama baik Anda menggunakanvar
ataulet
, misalnya:function foo() { var i = 0; while (Math.random() < 0.5) { ++i; } return i; }
Itu semua, tentu saja, tidak mungkin menjadi masalah dan sesuatu yang perlu dikhawatirkan hanya jika dan ketika ada masalah nyata untuk dipecahkan.
sumber
let
contoh loop juga. Perbedaan kinerja tidak perlu dikhawatirkan dalam kasus 99,999%."LET" LEBIH BAIK DALAM DEKLARASI LOOP
Dengan tes sederhana (5 kali) di navigator seperti itu:
// WITH VAR console.time("var-time") for(var i = 0; i < 500000; i++){} console.timeEnd("var-time")
Waktu rata-rata untuk mengeksekusi lebih dari 2,5 md
// WITH LET console.time("let-time") for(let i = 0; i < 500000; i++){} console.timeEnd("let-time")
Waktu rata-rata untuk mengeksekusi lebih dari 1,5 md
Saya menemukan bahwa waktu loop dengan let lebih baik.
sumber
var=138.8ms
danlet=4ms
. Itu bukan salah ketik,let
sekarang lebih dari 30x kali lebih cepatvar=2.6ms
danlet=1.0ms
. Jadi biarkan Node sedikit lebih dari dua kali lebih cepat.Jawaban TJ Crowder sangat bagus.
Berikut adalah tambahan dari: "Kapan saya akan mendapatkan hasil maksimal dari mengedit deklarasi var yang ada ke const?"
Saya telah menemukan bahwa peningkatan kinerja yang paling berkaitan dengan fungsi "diekspor".
Jadi, jika file A, B, R, dan Z memanggil fungsi "utilitas" di file U yang biasanya digunakan melalui aplikasi Anda, alihkan fungsi utilitas tersebut ke "const" dan referensi file induk ke konstanta dapat keluar beberapa peningkatan kinerja. Bagi saya, tampaknya itu tidak lebih cepat, tetapi konsumsi memori secara keseluruhan berkurang sekitar 1-3% untuk aplikasi saya yang sangat monolitik dengan Frankenstein. Yang mana jika Anda menghabiskan banyak uang di cloud atau server baremetal Anda, bisa menjadi alasan yang baik untuk menghabiskan 30 menit untuk menyisir dan memperbarui beberapa dari deklarasi var tersebut ke const.
Saya menyadari bahwa jika Anda membaca bagaimana const, var, dan membiarkan bekerja di bawah selimut, Anda mungkin sudah menyimpulkan hal di atas ... tetapi jika Anda "melirik" di atasnya: D.
Dari apa yang saya ingat tentang pembandingan pada node v8.12.0 ketika saya membuat pembaruan, aplikasi saya beralih dari konsumsi idle ~ 240MB RAM menjadi ~ 233MB RAM.
sumber
Jawaban TJ Crowder sangat bagus tetapi:
Pengaruh celah kinerja antara var dan let dapat dilihat dalam program lengkap kehidupan nyata dan bukan pada satu loop dasar.
Bagaimanapun, untuk menggunakan let di mana Anda tidak perlu, membuat kode Anda kurang dapat dibaca.
sumber
let
lebih lambat darivar
? Terutama mengingat konsensus dalam komentar pada jawaban di atas menunjukkan itu lebih cepat?