Saya sudah mendengar ini beberapa kali. Apakah loop JavaScript benar-benar lebih cepat saat menghitung mundur? Jika demikian, mengapa? Saya telah melihat beberapa contoh test suite yang menunjukkan bahwa loop terbalik lebih cepat, tetapi saya tidak dapat menemukan penjelasan mengapa!
Saya berasumsi itu karena loop tidak lagi harus mengevaluasi properti setiap kali memeriksa untuk melihat apakah sudah selesai dan hanya memeriksa terhadap nilai numerik akhir.
Yaitu
for (var i = count - 1; i >= 0; i--)
{
// count is only evaluated once and then the comparison is always on 0.
}
for
Loop mundur lebih cepat karena variabel kontrol loop atas-terikat (hehe, -batas) tidak harus didefinisikan atau diambil dari objek; ini adalah nol konstan.Jawaban:
Bukan itu
i--
lebih cepat daripadai++
. Sebenarnya, keduanya sama-sama cepat.Apa yang membutuhkan waktu dalam loop menanjak adalah mengevaluasi, untuk masing-masing
i
, ukuran array Anda. Dalam lingkaran ini:Anda mengevaluasi
.length
hanya sekali, ketika Anda menyatakani
, sedangkan untuk loop iniAnda mengevaluasi
.length
setiap kali Anda menambahi
, ketika Anda memeriksa apakahi <= array.length
.Dalam kebanyakan kasus Anda bahkan tidak perlu khawatir tentang optimasi semacam ini .
sumber
.length
beberapa kali atau untuk mendeklarasikan dan mendefinisikan variabel baru? Dalam kebanyakan kasus, ini adalah optimasi prematur (dan salah), kecuali Andalength
sangat mahal untuk mengevaluasi.0
lebih cepat untuk mengevaluasi daripadaarray.length
. Yah, seharusnya..length
dalam deklarasifor loop
atau tidak.Orang ini membandingkan banyak loop di javascript, di banyak browser. Ia juga memiliki ruang uji sehingga Anda dapat menjalankannya sendiri.
Dalam semua kasus (kecuali saya melewatkan satu di baca saya) loop tercepat adalah:
sumber
--i
maka Anda harus menggunakanvar current = arr[i-1];
di dalam loop atau akan dimatikan oleh satu ...Saya mencoba memberikan gambaran luas dengan jawaban ini.
Pikiran berikut dalam kurung adalah keyakinan saya sampai saya baru saja menguji masalah ini:
[[Dalam hal bahasa tingkat rendah seperti C / C ++ , kode dikompilasi sehingga prosesor memiliki perintah lompat kondisional khusus ketika sebuah variabel nol (atau tidak nol).
Juga, jika Anda peduli tentang banyak optimasi ini, Anda bisa pergi
++i
bukani++
karena++i
merupakan perintah prosesor tunggal sedangkani++
saranaj=i+1, i=j
.]]Loop sangat cepat dapat dilakukan dengan membuka gulungannya:
Ini bisa jadi lebih lambat dari pada
tetapi alasan untuk ini bisa sangat rumit (hanya untuk menyebutkan, ada masalah preprocessing perintah prosesor dan penanganan cache dalam game).
Dalam hal bahasa tingkat tinggi , seperti JavaScript saat Anda bertanya, Anda dapat mengoptimalkan berbagai hal jika Anda mengandalkan perpustakaan, fungsi bawaan untuk perulangan. Biarkan mereka memutuskan cara terbaik untuk melakukannya.
Akibatnya, dalam JavaScript, saya akan menyarankan menggunakan sesuatu seperti
Ini juga lebih rentan kesalahan dan browser memiliki kesempatan untuk mengoptimalkan kode Anda.
[KETINGGALAN: tidak hanya browser, tetapi Anda juga memiliki ruang untuk mengoptimalkan dengan mudah, cukup mendefinisikan kembali
forEach
fungsi (tergantung browser) sehingga menggunakan tipuan terbaik terbaru! :) @AMK mengatakan dalam kasus khusus layak menggunakanarray.pop
atauarray.shift
. Jika Anda melakukannya, letakkan di balik tirai. The maksimal berlebihan adalah dengan menambahkan pilihan untukforEach
memilih algoritma perulangan.]Selain itu, juga untuk bahasa tingkat rendah, praktik terbaik adalah menggunakan beberapa fungsi pustaka pintar untuk operasi yang rumit dan berulang jika memungkinkan.
Pustaka-pustaka itu juga dapat meletakkan hal-hal (multi-threaded) di belakang Anda dan juga pemrogram khusus membuat mereka tetap terbarui.
Saya melakukan sedikit pemeriksaan lebih lanjut dan ternyata di C / C ++, bahkan untuk operasi 5e9 = (50,000x100,000), tidak ada perbedaan antara naik dan turun jika pengujian dilakukan terhadap konstanta seperti kata @alestanis. (Hasil JsPerf kadang-kadang tidak konsisten tetapi pada umumnya mengatakan hal yang sama: Anda tidak dapat membuat perbedaan besar.)
Jadi
--i
kebetulan itu menjadi hal yang "mewah". Itu hanya membuat Anda terlihat seperti programmer yang lebih baik. :)Di sisi lain, untuk membuka gulungan dalam situasi 5e9 ini, itu membuat saya turun dari 12 detik menjadi 2,5 detik ketika saya naik 10 detik, dan 2,1 detik ketika saya pergi 20 tahun. Itu tanpa optimasi, dan optimasi telah membawa segalanya ke waktu yang tidak terukur. :) (Membuka gulungan dapat dilakukan dengan cara saya di atas atau menggunakan
i++
, tetapi itu tidak membawa hal-hal di depan dalam JavaScript.)Semua dalam semua: pertahankan
i--
/i++
dan++i
/i++
perbaiki wawancara pekerjaan, tetap padaarray.forEach
atau fungsi perpustakaan kompleks lainnya jika tersedia. ;)sumber
array.each(...)
. Saya tidak berpikir mereka akan mencoba dan bereksperimen dengan loop forloop polos.+1
untuk mendapatkan AndaGreat Answer
Lencana. Jawaban yang sangat bagus. :)i--
secepati++
Kode di bawah ini secepat milik Anda, tetapi menggunakan variabel tambahan:
Rekomendasi adalah untuk TIDAK mengevaluasi ukuran array setiap kali. Untuk array besar kita dapat melihat penurunan kinerja.
sumber
for (var i=0, up=Things.length; i<up; i++) {}
Karena, Anda tertarik pada subjek, lihat posting weblog Greg Reimer tentang tolok ukur loop JavaScript, Apa Cara Tercepat untuk Kode Loop dalam JavaScript? :
Anda juga dapat melakukan tes kinerja pada loop dengan membuka
https://blogs.oracle.com/greimer/resource/loop-test.html
(tidak berfungsi jika JavaScript diblokir di browser oleh, misalnya, NoScript ).EDIT:
Patokan yang lebih baru yang dibuat oleh Milan Adamovsky dapat dilakukan secara run-time di sini untuk berbagai browser.
Untuk Pengujian di Firefox 17.0 pada Mac OS X 10.6 saya mendapat loop berikut:
sebagai yang tercepat didahului oleh:
sumber
Ini bukan
--
atau++
, itu adalah operasi perbandingan. Dengan--
Anda dapat menggunakan membandingkan dengan 0, sedangkan dengan++
Anda harus membandingkannya dengan panjang. Pada prosesor, bandingkan dengan nol biasanya tersedia, sementara membandingkan dengan bilangan bulat terbatas membutuhkan pengurangan.a++ < length
sebenarnya dikompilasi sebagai
Jadi butuh waktu lebih lama pada prosesor saat dikompilasi.
sumber
Jawaban singkat
Untuk kode normal, terutama dalam bahasa tingkat tinggi seperti JavaScript , tidak ada perbedaan kinerja dalam
i++
dani--
.Kriteria kinerja adalah penggunaan dalam
for
loop dan pernyataan pembanding .Ini berlaku untuk semua bahasa tingkat tinggi dan sebagian besar independen dari penggunaan JavaScript. Penjelasannya adalah kode assembler yang dihasilkan di garis bawah.
Penjelasan detail
Perbedaan kinerja dapat terjadi dalam satu lingkaran. Latar belakangnya adalah bahwa pada tingkat kode assembler Anda dapat melihat bahwa
compare with 0
hanya satu pernyataan yang tidak memerlukan register tambahan.Perbandingan ini dikeluarkan pada setiap lintasan loop dan dapat menghasilkan peningkatan kinerja yang terukur.
akan dievaluasi ke kode semu seperti ini:
Perhatikan bahwa 0 adalah literal, atau dengan kata lain, nilai konstan.
akan dievaluasi menjadi kode pseudo seperti ini (yang diharapkan dari optimalisasi juru bahasa):
Perhatikan bahwa end adalah variabel yang membutuhkan register CPU . Ini dapat meminta register tambahan yang bertukar kode dan membutuhkan pernyataan perbandingan yang lebih mahal dalam
if
pernyataan tersebut.Hanya 5 sen saya
Untuk bahasa tingkat tinggi, keterbacaan, yang memfasilitasi pemeliharaan, lebih penting sebagai peningkatan kinerja kecil.
Biasanya iterasi klasik dari awal hingga akhir lebih baik.
Iterasi yang lebih cepat dari ujung array untuk memulai hasil dalam urutan terbalik yang mungkin tidak diinginkan.
Posting scriptum
Seperti yang ditanyakan dalam komentar: Perbedaan
--i
dani--
dalam evaluasii
sebelum atau sesudah pengurangan.Penjelasan terbaik adalah untuk mencobanya ;-) Ini adalah contoh Bash .
sumber
--i
dani--
juga?Saya telah melihat rekomendasi yang sama di Sublime Text 2.
Seperti yang sudah dikatakan, peningkatan utama tidak mengevaluasi panjang array pada setiap iterasi dalam for loop. Ini adalah teknik optimasi yang terkenal dan sangat efisien dalam JavaScript ketika array adalah bagian dari dokumen HTML (melakukan
for
untuk semuali
elemen).Sebagai contoh,
for (var i = 0; i < document.getElementsByTagName('li').length; i++)
jauh lebih lambat daripada
for (var i = 0, len = document.getElementsByTagName('li').length; i < len; i++)
Dari tempat saya berdiri, peningkatan utama dalam formulir dalam pertanyaan Anda adalah fakta bahwa itu tidak mendeklarasikan variabel tambahan (
len
dalam contoh saya)Tetapi jika Anda bertanya kepada saya, intinya bukan tentang optimasi
i++
vsi--
, tetapi tentang tidak harus mengevaluasi panjang array pada setiap iterasi (Anda dapat melihat tes benchmark pada jsperf ).sumber
Saya tidak berpikir masuk akal untuk mengatakan bahwa
i--
itu lebih cepat darii++
pada JavaScript.Pertama-tama , itu sepenuhnya tergantung pada implementasi mesin JavaScript.
Kedua , asalkan konstruk JIT'ed yang paling sederhana dan diterjemahkan menjadi instruksi asli, lalu
i++
vsi--
akan sepenuhnya bergantung pada CPU yang mengeksekusinya. Artinya, pada ARM (ponsel) lebih cepat turun ke 0 sejak penurunan dan dibandingkan dengan nol dieksekusi dalam satu instruksi.Mungkin, Anda berpikir bahwa yang satu lebih buas daripada yang lain karena cara yang disarankan adalah
tetapi cara yang disarankan bukan karena yang satu lebih cepat dari yang lain, tetapi hanya karena jika Anda menulis
maka pada setiap iterasi
array.length
harus dievaluasi (mesin JavaScript yang lebih cerdas mungkin bisa mengetahui bahwa loop tidak akan mengubah panjang array). Meskipun terlihat seperti pernyataan sederhana, sebenarnya beberapa fungsi yang dipanggil di bawah kap oleh mesin JavaScript.Alasan lain, mengapa
i--
bisa dianggap "lebih cepat" adalah karena mesin JavaScript perlu mengalokasikan hanya satu variabel internal untuk mengontrol loop (variabel kevar i
). Jika Anda dibandingkan dengan array.length atau beberapa variabel lain, maka harus ada lebih dari satu variabel internal untuk mengontrol loop, dan jumlah variabel internal adalah aset terbatas mesin JavaScript. Semakin sedikit variabel yang digunakan dalam satu lingkaran semakin banyak peluang JIT untuk optimasi. Itu sebabnyai--
bisa dianggap lebih cepat ...sumber
array.length
dievaluasi. Panjangnya tidak dihitung saat Anda merujuknya. (Ini hanya properti yang disetel setiap kali indeks array dibuat atau diubah ). Ketika ada biaya tambahan, itu karena mesin JS belum mengoptimalkan rantai pencarian untuk nama itu.getLength(){return m_length; }
karena ada beberapa housekeeping yang terlibat. Tetapi jika Anda mencoba untuk berpikir mundur: itu akan cukup cerdik untuk menulis implementasi array di mana panjang harus benar-benar dihitung :)length
harus diperbarui segera setiap kali properti-yang-adalah-sebuah-array-index ditambahkan atau diubah.dec/jnz
vs.inc eax / cmp eax, edx / jne
.Karena tidak ada jawaban lain yang tampaknya menjawab pertanyaan spesifik Anda (lebih dari setengahnya menunjukkan contoh C dan membahas bahasa tingkat rendah, pertanyaan Anda adalah JavaScript). Saya memutuskan untuk menulis sendiri.
Jadi, ini dia:
Jawaban sederhana:
i--
umumnya lebih cepat karena tidak harus menjalankan perbandingan dengan 0 setiap kali berjalan, hasil pengujian pada berbagai metode di bawah ini:Hasil tes: Seperti "dibuktikan" oleh jsPerf ini ,
arr.pop()
sebenarnya adalah loop tercepat sejauh ini. Tapi, berfokus pada--i
,i--
,i++
dan++i
seperti yang Anda minta dalam pertanyaan Anda, di sini adalah jsPerf (mereka dari beberapa jsPerf, silakan lihat sumber di bawah ini) hasil diringkas:--i
dani--
sama di Firefox sementarai--
lebih cepat di Chrome.Di Chrome, dasar untuk loop (
for (var i = 0; i < arr.length; i++)
) lebih cepat darii--
dan--i
sementara di Firefox lebih lambat.Di Chrome dan Firefox keduanya di-cache
arr.length
lebih cepat secara signifikan dengan Chrome unggul sekitar 170.000 ops / detik.Tanpa perbedaan yang signifikan,
++i
lebih cepat darii++
pada kebanyakan browser, AFAIK, tidak pernah sebaliknya di browser apa pun.Ringkasan yang lebih pendek:
arr.pop()
adalah putaran tercepat sejauh ini; untuk loop yang disebutkan secara khusus,i--
adalah loop tercepat.Sumber: http://jsperf.com/fastest-array-loops-in-javascript/15 , http://jsperf.com/ipp-vs-ppi-2
Saya harap ini menjawab pertanyaan Anda.
sumber
pop
tes Anda tampaknya cukup cepat karena mengurangi ukuran array menjadi 0 untuk sebagian besar loop - sejauh yang saya tahu. Namun untuk memastikan semuanya adil, saya telah merancang jsperf ini untuk membuat array dengan cara yang sama dengan setiap tes - yang tampaknya menunjukkan.shift()
sebagai pemenang untuk beberapa browser saya - bukan apa yang saya harapkan :) jsperf.com / bandingkan-berbagai-jenis-perulangan++i
: DItu tergantung pada penempatan array Anda di memori dan rasio hit halaman memori saat Anda mengakses array itu.
Dalam beberapa kasus mengakses anggota array dalam urutan kolom lebih cepat daripada urutan baris karena peningkatan rasio hit.
sumber
Terakhir kali saya peduli tentang itu ketika menulis 6502 perakitan (8-bit, yeah!). Keuntungan besar adalah bahwa sebagian besar operasi aritmatika (terutama pengurangan) memperbarui satu set bendera, salah satunya adalah
Z
, indikator 'mencapai nol'.Jadi, pada akhir loop Anda baru saja melakukan dua instruksi:
DEC
(decrement) danJNZ
(melompat jika tidak nol), tidak diperlukan perbandingan!sumber
i--
vsi++
adalah bahwa dengan yang sebelumnya Anda tidak memperkenalkan variabel kontrol tambahan dalam lingkup loop. Lihat jawaban saya di bawah ini ...dec/jnz
alih-alihinc/cmp/jne
untuk kasus x86. Anda tidak akan melihat loop kosong berjalan lebih cepat (keduanya akan menjenuhkan throughput cabang), tetapi menghitung mundur sedikit mengurangi overhead loop. Prefetcher Intel HW saat ini juga tidak terganggu oleh pola akses memori yang berjalan dalam urutan menurun. CPU yang lebih lama Saya pikir bisa melacak seperti 4 stream mundur dan 6 atau 10 stream maju, IIRC.Ini dapat dijelaskan oleh JavaScript (dan semua bahasa) yang pada akhirnya diubah menjadi opcode untuk dijalankan pada CPU. CPU selalu memiliki instruksi tunggal untuk membandingkan dengan nol, yang sangat cepat.
Sebagai tambahan, jika Anda dapat menjamin
count
selalu>= 0
, Anda dapat menyederhanakan untuk:sumber
Ini tidak tergantung pada tanda
--
atau++
, tetapi tergantung pada kondisi yang Anda terapkan dalam loop.Sebagai contoh: Loop Anda lebih cepat jika variabel memiliki nilai statis daripada jika loop Anda memeriksa kondisi setiap saat, seperti panjang array atau kondisi lainnya.
Tetapi jangan khawatir tentang pengoptimalan ini, karena kali ini pengaruhnya diukur dalam nanodetik.
sumber
for(var i = array.length; i--; )
tidak jauh lebih cepat. Tetapi ketika Anda menggantinyaarray.length
dengansuper_puper_function()
, itu mungkin jauh lebih cepat (karena itu disebut di setiap iterasi). Itulah bedanya.Jika Anda akan mengubahnya pada 2014, Anda tidak perlu memikirkan pengoptimalan. Jika Anda akan mengubahnya dengan "Cari & Ganti", Anda tidak perlu memikirkan pengoptimalan. Jika Anda tidak punya waktu, Anda tidak perlu memikirkan pengoptimalan. Tapi sekarang, Anda punya waktu untuk memikirkannya.
PS:
i--
tidak lebih cepat darii++
.sumber
Singkatnya: Sama sekali tidak ada perbedaan dalam melakukan ini dalam JavaScript.
Pertama-tama, Anda dapat mengujinya sendiri:
jsperf - adalah platform yang sangat baik untuk semua jenis pengujian kinerja dalam JavaScript .
http://jsperf.com/inc-vs-dec-2
Anda tidak hanya dapat menguji dan menjalankan skrip apa pun di pustaka JavaScript apa pun, tetapi Anda juga memiliki akses ke sejumlah skrip yang ditulis sebelumnya, serta kemampuan untuk melihat perbedaan antara waktu eksekusi di berbagai browser pada platform yang berbeda.
Jadi sejauh yang Anda bisa lihat, tidak ada perbedaan antara kinerja di lingkungan apa pun.
Jika Anda ingin meningkatkan kinerja skrip Anda, hal-hal yang dapat Anda coba lakukan:
var a = array.length;
pernyataan sehingga Anda tidak akan menghitung nilainya setiap kali dalam loopTetapi Anda harus memahami bahwa peningkatan yang dapat Anda peroleh akan sangat kecil, sehingga sebagian besar Anda bahkan tidak perlu mempedulikannya.
Pendapat saya sendiri mengapa kesalahpahaman seperti itu (Dec vs Inc) muncul
Dahulu kala ada instruksi mesin yang umum, DSZ (Decrement and Skip on Zero). Orang-orang yang diprogram dalam bahasa assembly menggunakan instruksi ini untuk mengimplementasikan loop untuk menyimpan register. Sekarang fakta kuno ini sudah usang, dan saya cukup yakin Anda tidak akan mendapatkan peningkatan kinerja dalam bahasa apa pun menggunakan perbaikan semu ini.
Saya pikir satu-satunya cara pengetahuan tersebut dapat berkembang di zaman kita adalah ketika Anda membaca kode orang lain. Lihat konstruksi seperti itu dan tanyakan mengapa itu diterapkan dan di sini jawabannya: "itu meningkatkan kinerja karena dibandingkan dengan nol". Anda menjadi bingung dengan pengetahuan yang lebih tinggi dari kolega Anda dan berpikir untuk menggunakannya agar lebih pintar :-)
sumber
array.length
tidak harus dikenakan penalti kinerja, hanya karena mesin virtual JS cukup pintar untuk mengetahui apakah array tidak dimodifikasi oleh tubuh loop. Lihat jawaban saya di bawah ini.Saya membuat perbandingan di jsbench .
Seperti yang ditunjukkan alestani, satu hal yang membutuhkan waktu dalam loop menanjak, adalah mengevaluasi, untuk setiap iterasi, ukuran array Anda. Dalam lingkaran ini:
Anda mengevaluasi
.length
setiap kali Anda menambahi
. Yang ini:Anda mengevaluasi
.length
hanya sekali, ketika Anda menyatakani
. Yang ini:perbandingannya implisit, itu terjadi sebelum decrementing
i
, dan kode ini sangat mudah dibaca. Namun, apa yang dapat membuat perbedaan luar biasa, adalah apa yang Anda masukkan ke dalam loop.Loop dengan fungsi panggilan ke (didefinisikan di tempat lain):
Ulangi dengan kode sebaris:
Jika Anda dapat memasukkan kode Anda, alih-alih memanggil fungsi, tanpa mengorbankan keterbacaan, Anda dapat membuat lingkaran dengan urutan lebih cepat!
Catatan : karena peramban menjadi bagus dalam inlining fungsi sederhana, itu sangat tergantung pada seberapa kompleks kode Anda. Jadi, profil sebelum dioptimalkan, karena
Tapi ingat:
sumber
Cara Anda melakukannya sekarang tidak lebih cepat (selain dari itu menjadi loop tidak terbatas, saya kira Anda harus melakukannya
i--
.Jika Anda ingin membuatnya lebih cepat, lakukan:
tentu saja Anda tidak akan melihatnya dalam lingkaran kecil. Alasannya lebih cepat adalah karena Anda mengurangi i sambil memeriksa bahwa itu "benar" (itu dinilai menjadi "salah" ketika mencapai 0)
sumber
(i = 10; i--;)
Terkadang membuat beberapa perubahan kecil pada cara kita menulis kode kita dapat membuat perbedaan besar pada seberapa cepat kode kita benar-benar berjalan. Satu area di mana perubahan kode kecil dapat membuat perbedaan besar untuk waktu eksekusi adalah di mana kita memiliki for loop yang memproses array. Di mana array adalah elemen pada halaman web (seperti tombol radio) perubahan memiliki efek terbesar tetapi masih layak menerapkan perubahan ini bahkan ketika array internal ke kode Javascript.
Cara konvensional mengkode loop for untuk memproses lis array seperti ini:
Masalah dengan ini adalah bahwa mengevaluasi panjang array menggunakan myArray.length membutuhkan waktu dan cara kita mengkodekan loop berarti evaluasi ini harus dilakukan setiap kali di sekitar loop. Jika array berisi 1000 elemen maka panjang array akan dievaluasi 1001 kali. Jika kita melihat tombol radio dan memiliki myForm.myButtons.length maka akan butuh waktu lebih lama untuk mengevaluasi karena kelompok tombol yang sesuai dalam formulir yang ditentukan harus terlebih dahulu ditemukan sebelum panjangnya dapat dievaluasi setiap kali di sekitar loop.
Jelas kami tidak berharap panjang array berubah saat kami memprosesnya sehingga semua perhitungan ulang panjang ini hanya menambah waktu pemrosesan yang tidak perlu. (Tentu saja jika Anda memiliki kode di dalam loop yang menambah atau menghapus entri array maka ukuran array dapat berubah di antara iterasi dan jadi kami tidak dapat mengubah kode yang mengujinya)
Apa yang bisa kita lakukan untuk memperbaiki ini untuk loop di mana ukurannya tetap adalah untuk mengevaluasi panjangnya sekali pada awal loop dan menyimpannya dalam variabel. Kami kemudian dapat menguji variabel untuk memutuskan kapan harus mengakhiri loop. Ini jauh lebih cepat daripada mengevaluasi panjang array setiap kali terutama ketika array berisi lebih dari beberapa entri atau merupakan bagian dari halaman web.
Kode untuk melakukan ini adalah:
Jadi sekarang kita hanya mengevaluasi ukuran array sekali dan menguji penghitung loop kita terhadap variabel yang memegang nilai itu setiap kali di sekitar loop. Variabel tambahan ini dapat diakses lebih cepat daripada mengevaluasi ukuran array dan kode kita akan berjalan lebih cepat dari sebelumnya. Kami hanya memiliki satu variabel tambahan dalam skrip kami.
Seringkali tidak masalah apa pun urutan kami memproses array selama semua entri dalam array diproses. Jika demikian, kita dapat membuat kode kita sedikit lebih cepat dengan menghapus variabel tambahan yang baru saja kita tambahkan dan memproses array dalam urutan terbalik.
Kode akhir yang memproses array kami dengan cara yang seefisien mungkin adalah:
Kode ini masih hanya mengevaluasi ukuran array sekali di awal tetapi alih-alih membandingkan penghitung loop dengan variabel kita membandingkannya dengan konstanta. Karena konstanta bahkan lebih efektif untuk diakses daripada variabel dan karena kita memiliki satu pernyataan penugasan yang lebih sedikit daripada sebelum versi ketiga kode kita sekarang sedikit lebih efisien daripada versi kedua dan jauh lebih efisien daripada yang pertama.
sumber
++
vs.--
tidak masalah karena JavaScript adalah bahasa yang ditafsirkan, bukan bahasa yang dikompilasi. Setiap instruksi diterjemahkan ke lebih dari satu bahasa mesin dan Anda tidak perlu peduli dengan detail darah.Orang-orang yang berbicara tentang menggunakan
--
(atau++
) menggunakan instruksi perakitan secara efisien adalah salah. Instruksi ini berlaku untuk bilangan bulat aritmatika dan tidak ada bilangan bulat dalam JavaScript, hanya angka .Anda harus menulis kode yang dapat dibaca.
sumber
Dalam banyak kasus, ini pada dasarnya tidak ada hubungannya dengan fakta bahwa prosesor dapat dibandingkan dengan nol lebih cepat daripada perbandingan lainnya.
Ini karena hanya beberapa mesin Javascript (yang ada di daftar JIT) yang benar-benar menghasilkan kode bahasa mesin.
Sebagian besar mesin Javascript membangun representasi internal dari kode sumber yang kemudian mereka tafsirkan (untuk mendapatkan gambaran seperti apa ini, lihat di dekat bagian bawah halaman ini tentang SpiderMonkey Firefox ). Umumnya jika sepotong kode melakukan hal yang sama tetapi mengarah ke representasi internal yang lebih sederhana, itu akan berjalan lebih cepat.
Ingatlah bahwa dengan tugas-tugas sederhana seperti menambah / mengurangi satu dari suatu variabel, atau membandingkan suatu variabel dengan sesuatu, overhead penerjemah bergerak dari satu "instruksi" internal ke yang berikutnya cukup tinggi, sehingga semakin sedikit "instruksi" yang ada. digunakan secara internal oleh mesin JS, semakin baik.
sumber
Yah, saya tidak tahu tentang JavaScript, itu harus benar-benar hanya masalah panjang array evaluasi ulang dan mungkin ada hubungannya dengan array asosiatif (jika Anda hanya mengurangi, itu tidak mungkin entri baru perlu dialokasikan - jika array padat, yaitu seseorang dapat mengoptimalkan untuk itu).
Dalam perakitan level rendah, ada instruksi looping, yang disebut DJNZ (decrement and jump jika tidak nol). Jadi penurunan dan lompatan adalah semua dalam satu instruksi, membuatnya mungkin jadi sedikit lebih cepat daripada INC dan JL / JB (kenaikan, lompat jika kurang dari / lompat jika di bawah). Juga, membandingkan dengan nol lebih sederhana daripada membandingkan dengan nomor lain. Tapi semua itu benar-benar marjinal dan juga tergantung pada arsitektur target (bisa membuat perbedaan misalnya pada Arm di smartphone).
Saya tidak berharap perbedaan tingkat rendah ini memiliki dampak besar pada bahasa yang ditafsirkan, saya hanya belum melihat DJNZ di antara tanggapan jadi saya pikir saya akan berbagi pemikiran yang menarik.
sumber
DJNZ
adalah instruksi dalam 8051 (z80) ISA. x86dec/jnz
bukaninc/cmp/jne
, dan tampaknya lengan memiliki sesuatu yang serupa. Saya cukup yakin ini bukan penyebab perbedaan Javascript; itu dari memiliki lebih banyak eval dalam kondisi loop.Itu digunakan untuk dikatakan bahwa -Saya lebih cepat (dalam C ++) karena hanya ada satu hasil, nilai dikurangi. i-- perlu menyimpan nilai yang dikurangi kembali ke i dan juga mempertahankan nilai asli sebagai hasilnya (j = i--;). Dalam kebanyakan kompiler, ini menggunakan dua register daripada satu yang dapat menyebabkan variabel lain harus dituliskan ke memori daripada disimpan sebagai variabel register.
Saya setuju dengan yang lain yang mengatakan tidak ada bedanya hari ini.
sumber
Dengan kata-kata yang sangat sederhana
"Aku-- dan aku ++. Sebenarnya, mereka berdua membutuhkan waktu yang sama".
tetapi dalam kasus ini ketika Anda memiliki operasi tambahan .. prosesor mengevaluasi .length setiap kali variabel bertambah 1 dan dalam kasus penurunan .. khususnya dalam kasus ini, ia akan mengevaluasi .length hanya sekali sampai kita mendapatkan 0.
sumber
Pertama,
i++
dani--
luangkan waktu yang sama persis pada bahasa pemrograman apa pun, termasuk JavaScript.Kode berikut membutuhkan waktu yang jauh berbeda.
Cepat:
Lambat:
Karena itu kode berikut juga membutuhkan waktu yang berbeda.
Cepat:
Lambat:
PS Slow lambat hanya untuk beberapa bahasa (mesin JavaScript) karena optimasi kompiler. Cara terbaik adalah menggunakan '<' sebagai gantinya '<=' (atau '=') dan '--i' sebagai gantinya 'i--' .
sumber
Tidak banyak waktu dikonsumsi oleh i-- atau i ++. Jika Anda masuk jauh ke dalam arsitektur CPU
++
lebih cepat daripada--
, karena--
operasi akan melakukan komplemen 2's, tetapi itu terjadi di dalam perangkat keras sehingga ini akan membuatnya cepat dan tidak ada perbedaan besar antara++
dan--
juga operasi ini dianggap sebagai paling tidak waktu yang digunakan dalam CPU.Untuk loop berjalan seperti ini:
<
,>
,<=
, dllBegitu,
akan menghitung panjang array hanya sekali di awal dan ini tidak banyak waktu, tetapi
akan menghitung panjang di setiap loop, sehingga akan menghabiskan banyak waktu.
sumber
var i = Things.length - 1; i >= 0; i--
akan menghitung panjang 1 kali juga.--
operasi akan melakukan komplemen 2", tetapi saya menganggap itu berarti akan meniadakan sesuatu. Tidak, itu tidak meniadakan apa pun pada arsitektur apa pun. Mengurangi 1 sama mudahnya dengan menambahkan 1, Anda hanya membuat sirkuit yang meminjam daripada membawa.Pendekatan terbaik untuk menjawab pertanyaan semacam ini adalah dengan benar-benar mencobanya. Atur loop yang menghitung sejuta iterasi atau apa pun, dan lakukan keduanya. Waktu kedua loop, dan bandingkan hasilnya.
Jawabannya mungkin tergantung pada browser yang Anda gunakan. Beberapa akan memiliki hasil yang berbeda dari yang lain.
sumber
Menyukainya, banyak tanda tetapi tidak ada jawaban: D
Sederhananya perbandingan terhadap nol selalu merupakan perbandingan tercepat
Jadi (a == 0) sebenarnya lebih cepat dalam mengembalikan True daripada (a == 5)
Ini kecil dan tidak signifikan dan dengan 100 juta baris dalam koleksi itu bisa diukur.
yaitu pada loop ke atas Anda mungkin mengatakan di mana i <= array.length dan akan bertambah i
pada loop bawah Anda mungkin mengatakan di mana i> = 0 dan akan mengurangi i.
Perbandingannya lebih cepat. Bukan 'arah' loop.
sumber
BANTUAN ORANG LAIN MENGHINDARI HEADACHE --- PILIH INI !!!
Jawaban paling populer di halaman ini tidak berfungsi untuk Firefox 14 dan tidak lulus jsLinter. "while" loop membutuhkan operator pembanding, bukan penugasan. Ia bekerja pada chrome, safari, dan bahkan ie. Tapi mati di firefox.
INI RUSAK!
INI AKAN BEKERJA! (bekerja pada firefox, melewati jsLinter)
sumber
while (i--)
dan yang bekerja di banyak browser. Mungkinkah ada sesuatu yang aneh dengan tes Anda? Apakah Anda menggunakan Firefox 14 versi beta?Ini hanya dugaan, tapi mungkin itu karena prosesor lebih mudah untuk membandingkan sesuatu dengan 0 (i> = 0) daripada dengan nilai lain (i <Things.length).
sumber