Di C # / VB.NET / .NET, loop mana yang berjalan lebih cepat, for
atau foreach
?
Sejak saya membaca bahwa for
lingkaran bekerja lebih cepat dari foreach
lingkaran waktu yang lalu saya diasumsikan itu berdiri berlaku untuk semua koleksi, koleksi generik, semua array, dll
Saya menjelajahi Google dan menemukan beberapa artikel, tetapi kebanyakan dari mereka tidak meyakinkan (baca komentar pada artikel) dan terbuka.
Apa yang ideal adalah membuat setiap skenario dicantumkan dan solusi terbaik untuk hal yang sama.
Misalnya (hanya contoh bagaimana seharusnya):
- untuk iterasi array 1000+ string -
for
lebih baik daripadaforeach
- untuk iterasi dari
IList
string (non generik) -foreach
lebih baik daripadafor
Beberapa referensi ditemukan di web untuk hal yang sama:
- Artikel asli agung lama oleh Emmanuel Schanzer
- CodeEject FOREACH Vs. UNTUK
- Blog - Ke
foreach
atau tidakforeach
, itulah pertanyaannya - Forum ASP.NET - NET 1.1 C #
for
vsforeach
[Sunting]
Terlepas dari aspek keterbacaannya, saya benar-benar tertarik pada fakta dan angka. Ada beberapa aplikasi di mana jarak terakhir dari optimasi kinerja tidak menjadi masalah.
sumber
foreach
alih-alihfor
dalam C #. Jika Anda melihat jawaban di sini tidak masuk akal sama sekali, itu sebabnya. Salahkan moderator, bukan jawaban yang malang.Jawaban:
Patrick Smacchia membuat blog tentang ini bulan lalu, dengan kesimpulan sebagai berikut:
sumber
foreach
daripada yang diperlukan untuk mengulang melalui array denganfor
, dan Anda memanggil itu tidak signifikan? Perbedaan kinerja semacam itu mungkin penting bagi aplikasi Anda, dan mungkin tidak, tetapi saya tidak akan mengabaikannya begitu saja.foreach
.Pertama, klaim balik terhadap jawaban Dmitry (sekarang dihapus) . Untuk array, kompiler C # memancarkan sebagian besar kode yang sama
foreach
seperti untukfor
loop setara . Itu menjelaskan mengapa untuk tolok ukur ini, hasilnya pada dasarnya sama:Hasil:
Selanjutnya, validasi bahwa poin Greg tentang jenis koleksi menjadi penting - ubah array menjadi
List<double>
di atas, dan Anda mendapatkan hasil yang sangat berbeda. Tidak hanya secara signifikan lebih lambat secara umum, tetapi juga menjadi lebih lambat secara signifikan daripada mengakses dengan indeks. Karena itu, saya masih hampir selalu lebih suka foreach untuk loop di mana ia membuat kode lebih sederhana - karena keterbacaan hampir selalu penting, sedangkan mikro-optimasi jarang.sumber
List<T>
? Apakah keterbacaan truf optimasi mikro dalam kasus itu juga?List<T>
daripada array. Pengecualiannya adalahchar[]
danbyte[]
yang lebih sering diperlakukan sebagai "potongan" data daripada koleksi normal.foreach
loop menunjukkan niat yang lebih spesifik daripadafor
loop .Menggunakan
foreach
loop menunjukkan kepada siapa pun yang menggunakan kode Anda bahwa Anda berencana untuk melakukan sesuatu kepada setiap anggota koleksi terlepas dari tempatnya dalam koleksi. Ini juga menunjukkan Anda tidak mengubah koleksi asli (dan melempar pengecualian jika Anda mencoba).Keuntungan lain
foreach
adalah bahwa ia bekerja pada apa punIEnumerable
, di manafor
hanya masuk akalIList
, di mana setiap elemen sebenarnya memiliki indeks.Namun, jika Anda perlu menggunakan indeks suatu elemen, maka tentu saja Anda harus diizinkan menggunakan
for
loop. Tetapi jika Anda tidak perlu menggunakan indeks, memilikinya hanya akan mengacaukan kode Anda.Tidak ada implikasi kinerja yang signifikan sejauh yang saya ketahui. Pada tahap tertentu di masa depan, mungkin lebih mudah untuk mengadaptasi kode yang digunakan
foreach
untuk berjalan pada banyak core, tapi itu bukan sesuatu yang perlu dikhawatirkan saat ini.sumber
foreach
.foreach
sama sekali tidak terkait dengan pemrograman fungsional. Ini benar - benar paradigma penting pemrograman. Anda salah menghubungkan hal-hal yang terjadi di TPL dan PLINQ keforeach
.foreach
sebagai setara denganwhile
loop). Saya rasa saya tahu yang dimaksud dengan @ctford. Pustaka paralel tugas memungkinkan koleksi yang mendasarinya untuk menyediakan elemen-elemen dalam urutan acak (dengan memanggil.AsParallel
enumerable).foreach
tidak melakukan apa pun di sini dan tubuh loop dijalankan pada satu utas . Satu-satunya hal yang diparalelkan adalah pembuatan urutan.foreach
danfor
kinerja untuk daftar normal adalah sepersekian detik untuk iterasi lebih dari jutaan item sehingga masalah Anda tentu tidak terkait langsung dengan kinerja foreach, setidaknya tidak untuk beberapa ratus objek. Kedengarannya seperti implementasi enumerator yang rusak di daftar apa pun yang Anda gunakan.Setiap kali ada argumen atas kinerja, Anda hanya perlu menulis tes kecil sehingga Anda dapat menggunakan hasil kuantitatif untuk mendukung kasus Anda.
Gunakan kelas StopWatch dan ulangi sesuatu beberapa juta kali, untuk akurasi. (Ini mungkin sulit tanpa loop):
Semoga hasil-hasil ini menunjukkan bahwa perbedaannya dapat diabaikan, dan Anda mungkin juga melakukan apa saja yang menghasilkan kode yang paling dapat dipertahankan.
sumber
Itu akan selalu dekat. Untuk sebuah array, kadang
for
- kadang sedikit lebih cepat, tetapiforeach
lebih ekspresif, dan menawarkan LINQ, dll. Secara umum, tetap denganforeach
.Selain itu,
foreach
dapat dioptimalkan dalam beberapa skenario. Misalnya, daftar tertaut mungkin mengerikan oleh pengindeks, tetapi mungkin cepatforeach
. Sebenarnya, standarLinkedList<T>
bahkan tidak menawarkan pengindeks karena alasan ini.sumber
LinkedList<T>
maksudmu lebih ramping dari ituList<T>
? Dan jika saya akan selalu menggunakanforeach
(bukannyafor
), saya lebih baik menggunakanLinkedList<T>
?List<T>
). Lebih dari itu lebih murah untuk memasukkan / menghapus .Dugaan saya adalah bahwa hal itu mungkin tidak akan signifikan dalam 99% kasus, jadi mengapa Anda memilih yang lebih cepat daripada yang paling tepat (seperti yang paling mudah dipahami / dipelihara)?
sumber
Tidak mungkin ada perbedaan kinerja yang sangat besar di antara keduanya. Seperti biasa, ketika dihadapkan dengan "mana yang lebih cepat?" pertanyaan, Anda harus selalu berpikir "Saya bisa mengukur ini."
Tulis dua loop yang melakukan hal yang sama di tubuh loop, jalankan dan beri waktu keduanya, dan lihat perbedaan kecepatannya. Lakukan ini dengan tubuh yang hampir kosong, dan tubuh melingkar yang mirip dengan apa yang sebenarnya akan Anda lakukan. Coba juga dengan jenis koleksi yang Anda gunakan, karena berbagai jenis koleksi dapat memiliki karakteristik kinerja yang berbeda.
sumber
Ada alasan yang sangat bagus untuk memilih
foreach
loop daripadafor
loop. Jika Anda dapat menggunakanforeach
loop, bos Anda benar bahwa Anda harus melakukannya.Namun, tidak setiap iterasi hanya melalui daftar secara berurutan. Jika dia melarang , ya itu salah.
Jika saya adalah Anda, apa yang akan saya lakukan adalah mengubah semua alami Anda untuk loop menjadi rekursi . Itu akan mengajarinya, dan itu juga latihan mental yang baik untuk Anda.
sumber
for
loop danforeach
loop kinerja-bijaksana?Jeffrey Richter di TechEd 2005:
Siaran Web Berdasarkan Permintaan: http://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?EventID=1032292286&EventCategory=3&culture=en-US&CountryCode=US
sumber
Ini konyol. Tidak ada alasan kuat untuk melarang perulangan, kinerja-bijaksana atau lainnya.
Lihat blog Jon Skeet untuk benchmark kinerja dan argumen lainnya.
sumber
Dalam kasus di mana Anda bekerja dengan koleksi objek,
foreach
lebih baik, tetapi jika Anda menambah angka, satufor
loop lebih baik.Perhatikan bahwa dalam kasus terakhir, Anda dapat melakukan sesuatu seperti:
Tetapi tentu saja tidak berkinerja lebih baik, itu sebenarnya memiliki kinerja yang lebih buruk dibandingkan dengan
for
.sumber
Ini akan menyelamatkan Anda:
Menggunakan:
Untuk kemenangan yang lebih besar, Anda dapat menggunakan tiga delegasi sebagai parameter.
sumber
for
loop biasanya ditulis untuk mengecualikan akhir rentang (misalnya0 <= i < 10
).Parallel.For
juga melakukan itu agar mudah dipertukarkan denganfor
loop umum .Anda dapat membacanya di Deep .NET - bagian 1 Iteration
itu mencakup hasil (tanpa inisialisasi pertama) dari kode sumber .NET sampai ke pembongkaran.
misalnya - Iterasi Array dengan loop foreach:
dan - daftar iterasi dengan foreach loop:
dan hasil akhirnya:
sumber
Perbedaan kecepatan dalam a
for
- danforeach
-loop kecil ketika Anda mengulangi struktur umum seperti array, daftar, dll, dan melakukanLINQ
kueri atas koleksi hampir selalu sedikit lebih lambat, meskipun lebih baik untuk menulis! Seperti yang dikatakan poster-poster lain, lebih baik ekspresif daripada milidetik kinerja ekstra.Apa yang belum dikatakan sejauh ini adalah bahwa ketika sebuah
foreach
loop dikompilasi, ia dioptimalkan oleh kompiler berdasarkan pada koleksi yang berulang-ulang. Itu berarti bahwa ketika Anda tidak yakin loop mana yang harus digunakan, Anda harus menggunakanforeach
loop - itu akan menghasilkan loop terbaik untuk Anda ketika akan dikompilasi. Lebih mudah dibaca juga.Keuntungan utama lainnya dengan
foreach
loop adalah bahwa jika implementasi koleksi Anda berubah (dari intarray
keList<int>
misalnya) makaforeach
loop Anda tidak akan memerlukan perubahan kode:Di atas adalah sama, apa pun jenis koleksi Anda, sedangkan di
for
loop Anda , berikut ini tidak akan membangun jika Anda berubahmyCollection
dari suatuarray
keList
:sumber
"Apakah ada argumen yang bisa saya gunakan untuk membantu saya meyakinkannya bahwa for loop dapat diterima untuk digunakan?"
Tidak, jika bos Anda melakukan manajemen mikro hingga memberi tahu Anda apa bahasa pemrograman yang harus digunakan, benar-benar tidak ada yang bisa Anda katakan. Maaf.
sumber
Mungkin tergantung pada jenis koleksi yang Anda hitung dan implementasi pengindeksnya. Namun secara umum, menggunakan
foreach
cenderung menjadi pendekatan yang lebih baik.Juga, itu akan bekerja dengan apa pun
IEnumerable
- bukan hanya hal-hal dengan pengindeks.sumber
Ini memiliki dua jawaban yang sama dengan sebagian besar pertanyaan "yang lebih cepat":
1) Jika Anda tidak mengukur, Anda tidak tahu.
2) (Karena ...) Itu tergantung.
Tergantung pada seberapa mahal metode "MoveNext ()", relatif terhadap seberapa mahal metode "ini [indeks]", untuk tipe (atau tipe) dari IEnumerable yang akan Anda ulangi.
Kata kunci "foreach" adalah kependekan dari serangkaian operasi - ia memanggil GetEnumerator () satu kali di IEnumerable, ia memanggil MoveNext () sekali per iterasi, ia melakukan pengecekan beberapa jenis, dan seterusnya. Hal yang paling mungkin memengaruhi pengukuran kinerja adalah biaya MoveNext () karena itu akan dipanggil O (N) kali. Mungkin murah, tapi mungkin juga tidak.
Kata kunci "untuk" terlihat lebih dapat diprediksi, tetapi di dalam sebagian besar loop "untuk" Anda akan menemukan sesuatu seperti "koleksi [indeks]". Ini terlihat seperti operasi pengindeksan array sederhana, tetapi sebenarnya adalah pemanggilan metode, yang biayanya sepenuhnya bergantung pada sifat koleksi yang Anda ulangi. Mungkin murah, tapi mungkin juga tidak.
Jika struktur yang mendasari koleksi pada dasarnya adalah daftar tertaut, MoveNext murah, tetapi pengindeks mungkin memiliki biaya O (N), membuat biaya sebenarnya untuk loop "untuk" O (N * N).
sumber
Setiap konstruksi bahasa memiliki waktu dan tempat yang tepat untuk penggunaan. Ada alasan mengapa bahasa C # memiliki empat pernyataan iterasi yang terpisah - masing-masing ada untuk tujuan tertentu, dan memiliki penggunaan yang sesuai.
Saya sarankan duduk dengan bos Anda dan mencoba menjelaskan secara rasional mengapa
for
loop memiliki tujuan. Ada kalanyafor
blok iterasi lebih jelas menggambarkan algoritma daripadaforeach
iterasi. Ketika ini benar, maka tepat untuk menggunakannya.Saya juga menunjukkan kepada atasan Anda - Performa tidak, dan seharusnya tidak menjadi masalah dengan cara praktis - ini lebih merupakan masalah ekspresi algoritma dengan cara yang ringkas, bermakna, dapat dipertahankan. Optimalisasi mikro seperti ini melewatkan titik optimalisasi kinerja sepenuhnya, karena setiap manfaat kinerja nyata akan datang dari desain ulang dan refactoring algoritmik, bukan restrukturisasi loop.
Jika, setelah diskusi rasional, masih ada pandangan otoriter ini, terserah Anda bagaimana melanjutkan. Secara pribadi, saya tidak akan senang bekerja di lingkungan di mana pemikiran rasional tidak disarankan, dan akan mempertimbangkan pindah ke posisi lain di bawah majikan yang berbeda. Namun, saya sangat menyarankan diskusi sebelum menjadi kesal - mungkin ada kesalahpahaman sederhana di tempat.
sumber
Ini adalah apa yang Anda lakukan di dalam loop yang memengaruhi kinerja, bukan konstruk looping aktual (dengan asumsi case Anda non-trivial).
sumber
Apakah
for
lebih cepat daripadaforeach
benar-benar selain itu intinya. Saya sangat ragu bahwa memilih satu di antara yang lain akan membuat dampak yang signifikan pada kinerja Anda.Cara terbaik untuk mengoptimalkan aplikasi Anda adalah melalui profil kode aktual. Itu akan menunjukkan metode yang paling banyak menghitung waktu kerja /. Optimalkan itu dulu. Jika kinerja masih tidak dapat diterima, ulangi prosedur.
Sebagai aturan umum saya akan merekomendasikan untuk menjauh dari optimasi mikro karena mereka jarang akan menghasilkan keuntungan yang signifikan. Satu-satunya pengecualian adalah ketika mengoptimalkan jalur panas teridentifikasi (yaitu jika profil Anda mengidentifikasi beberapa metode yang sangat digunakan, mungkin masuk akal untuk mengoptimalkannya secara luas).
sumber
for
sedikit lebih cepat dariforeach
. Saya benar-benar keberatan dengan pernyataan ini. Itu benar-benar tergantung pada koleksi yang mendasarinya. Jika kelas daftar tertaut menyediakan pengindeks dengan parameter integer, saya akan berharap menggunakanfor
loop di atasnya menjadi O (n ^ 2) sementaraforeach
diharapkan menjadi O (n).for
dan pencarian pengindeksan untuk menggunakanforeach
dengan sendirinya. Saya pikir jawaban @Brian Rasmussen benar bahwa, selain dari penggunaan dengan koleksi,for
akan selalu sedikit lebih cepat daripadaforeach
. Namun,for
ditambah pencarian koleksi akan selalu lebih lambat daripadaforeach
dengan sendirinya.for
pernyataan.for
Loop biasa dengan variabel kontrol integer tidak sebanding denganforeach
, jadi itu keluar. Saya mengerti apa artinya @Brian dan itu benar seperti yang Anda katakan tetapi jawabannya bisa menyesatkan. Re: poin terakhir Anda: tidak, sebenarnya,for
overList<T>
masih lebih cepat dariforeach
.Keduanya akan berjalan dengan cara yang hampir persis sama. Tulis beberapa kode untuk menggunakan keduanya, lalu tunjukkan padanya IL. Ini harus menunjukkan perhitungan yang sebanding, yang berarti tidak ada perbedaan dalam kinerja.
sumber
karena memiliki logika yang lebih sederhana untuk diimplementasikan sehingga lebih cepat daripada foreach.
sumber
Kecuali Anda sedang dalam proses optimasi kecepatan tertentu, saya akan mengatakan menggunakan metode apa pun yang menghasilkan kode termudah untuk membaca dan memelihara.
Jika iterator sudah diatur, seperti dengan salah satu kelas koleksi, maka foreach adalah pilihan yang mudah dan bagus. Dan jika rentang integer yang Anda iterasi, maka untuk mungkin lebih bersih.
sumber
Jeffrey Richter membicarakan perbedaan kinerja antara for dan foreach di podcast baru-baru ini: http://pixel8.infragistics.com/shows/everything.aspx#Episode:9317
sumber
Dalam kebanyakan kasus tidak ada perbedaan.
Biasanya Anda selalu harus menggunakan foreach ketika Anda tidak memiliki indeks numerik eksplisit, dan Anda selalu harus menggunakan ketika Anda tidak benar-benar memiliki koleksi iterable (misalnya iterasi di atas grid array dua dimensi dalam segitiga atas) . Ada beberapa kasus di mana Anda punya pilihan.
Orang bisa berpendapat bahwa untuk loop bisa sedikit lebih sulit untuk dipertahankan jika angka ajaib mulai muncul dalam kode. Anda seharusnya merasa kesal karena tidak dapat menggunakan for for loop dan harus membuat koleksi atau menggunakan lambda untuk membangun subkoleksi alih-alih hanya karena untuk loop telah dilarang.
sumber
Tampaknya agak aneh untuk sepenuhnya melarang penggunaan sesuatu seperti for loop.
Ada artikel yang menarik di sini yang membahas banyak perbedaan kinerja antara kedua loop.
Saya akan mengatakan secara pribadi saya menemukan foreach sedikit lebih mudah dibaca untuk loop tetapi Anda harus menggunakan yang terbaik untuk pekerjaan di tangan dan tidak harus menulis kode ekstra panjang untuk menyertakan foreach loop jika for for loop lebih tepat.
sumber
Saya menemukan
foreach
loop yang iterasi melaluiList
lebih cepat . Lihat hasil pengujian saya di bawah ini. Dalam kode di bawah ini saya mengulangiarray
ukuran 100, 10.000 dan 100000 secara terpisah menggunakanfor
danforeach
loop untuk mengukur waktu.DIPERBARUI
Setelah saran @jgauffin saya menggunakan kode @johnskeet dan menemukan bahwa
for
loop denganarray
lebih cepat daripada mengikuti,Lihat hasil tes dan kode saya di bawah ini,
sumber
Anda benar-benar dapat mengacaukan kepalanya dan melakukan IQueryable. Penutupan sebaliknya:
sumber
myList.ForEach(Console.WriteLine)
.Saya tidak akan mengharapkan siapa pun untuk menemukan perbedaan kinerja "besar" antara keduanya.
Saya kira jawabannya tergantung pada apakah kumpulan yang Anda coba akses memiliki implementasi akses pengindeks yang lebih cepat atau implementasi akses IEnumerator yang lebih cepat. Karena IEnumerator sering menggunakan pengindeks dan hanya memegang salinan posisi indeks saat ini, saya berharap akses enumerator setidaknya sama lambat atau lebih lambat dari akses indeks langsung, tetapi tidak banyak.
Tentu saja jawaban ini tidak memperhitungkan optimisasi apa pun yang mungkin diterapkan oleh kompiler.
sumber
Perlu diingat bahwa for-loop dan foreach-loop tidak selalu setara. Daftar enumerator akan mengeluarkan pengecualian jika daftar berubah, tetapi Anda tidak akan selalu mendapatkan peringatan itu dengan loop normal. Anda bahkan mungkin mendapatkan pengecualian berbeda jika daftar berubah pada waktu yang salah.
sumber