Pertama-tama, saya mengerti dalam 90% aplikasi perbedaan kinerja sama sekali tidak relevan, tetapi saya hanya perlu tahu mana yang lebih cepat membangun. Itu dan ...
Informasi yang tersedia saat ini di internet membingungkan. Banyak orang mengatakan foreach itu buruk, tetapi secara teknis seharusnya lebih cepat karena itu menyederhanakan menulis array array menggunakan iterators. Iterator, yang sekali lagi dianggap lebih cepat, tetapi dalam PHP juga tampaknya lambat lambat (atau ini bukan PHP?). Saya berbicara tentang fungsi-fungsi array: next () prev () reset () dll. Baik, jika mereka bahkan berfungsi dan bukan salah satu dari fitur bahasa PHP yang terlihat seperti fungsi.
Untuk mempersempit ini sedikit : Saya tidak menarik melintasi array dalam langkah-langkah lebih dari 1 (tidak ada langkah negatif juga, yaitu. Iterasi terbalik). Saya juga tidak tertarik pada traversal ke dan dari titik arbitrer, hanya 0 panjangnya. Saya juga tidak melihat memanipulasi array dengan lebih dari 1000 tombol yang terjadi secara teratur, tetapi saya memang melihat array yang dilalui beberapa kali dalam logika aplikasi! Juga untuk operasi, sebagian besar hanya manipulasi string dan echo'ing.
Berikut adalah beberapa situs referensi:
http://www.phpbench.com/
http://www.php.lt/benchmark/phpbench.php
Apa yang saya dengar di mana-mana:
foreach
lambat, dan dengan demikianfor
/while
lebih cepat- PHP
foreach
menyalin array yang diulanginya ; untuk membuatnya lebih cepat, Anda perlu menggunakan referensi - kode seperti ini: lebih cepat dari a
$key = array_keys($aHash); $size = sizeOf($key);
for ($i=0; $i < $size; $i++)foreach
Inilah masalah saya. Saya menulis skrip pengujian ini: http://pastebin.com/1ZgK07US dan tidak peduli berapa kali saya menjalankan skrip, saya mendapatkan sesuatu seperti ini:
foreach 1.1438131332397
foreach (using reference) 1.2919359207153
for 1.4262869358063
foreach (hash table) 1.5696921348572
for (hash table) 2.4778981208801
Pendeknya:
foreach
lebih cepat daripadaforeach
dengan referensiforeach
lebih cepat darifor
foreach
lebih cepat daripadafor
untuk tabel hash
Bisakah seseorang menjelaskan?
- Apakah saya melakukan sesuatu yang salah?
- Apakah referensi PHP foreach benar-benar membuat perbedaan? Maksud saya mengapa tidak menyalinnya jika Anda melewati referensi?
- Apa kode iterator yang setara untuk pernyataan foreach; Saya telah melihat beberapa di internet tetapi setiap kali saya mengujinya, waktunya tidak tepat; Saya juga telah menguji beberapa konstruksi iterator sederhana tetapi sepertinya tidak pernah mendapatkan hasil yang layak - apakah array iterators di PHP hanya buruk?
- Apakah ada cara / metode / konstruk yang lebih cepat untuk beralih melalui array selain FOR / FOREACH (dan WHILE)?
PHP Versi 5.3.0
Sunting: Jawab Dengan bantuan dari orang-orang di sini saya dapat mengumpulkan jawaban untuk semua pertanyaan. Saya akan meringkasnya di sini:
- "Apakah aku melakukan sesuatu yang salah?" Tampaknya konsensus: ya, saya tidak bisa menggunakan gema dalam tolok ukur. Secara pribadi, saya masih tidak melihat bagaimana gema adalah suatu fungsi dengan waktu eksekusi yang acak atau bagaimana fungsi lainnya entah bagaimana berbeda - itu dan kemampuan skrip itu untuk hanya menghasilkan hasil yang sama persis dari foreach lebih baik daripada semuanya sulit untuk menjelaskan meskipun hanya "Anda menggunakan gema" (baik apa yang seharusnya saya gunakan). Namun, saya mengakui tes harus dilakukan dengan sesuatu yang lebih baik; meskipun kompromi yang ideal tidak terlintas dalam pikiran.
- "Apakah referensi PHP foreach benar-benar membuat perbedaan? Maksudku mengapa itu tidak akan menyalinnya jika Anda melewati referensi?" ircmaxell menunjukkan bahwa ya, pengujian lebih lanjut tampaknya membuktikan dalam banyak kasus, referensi harus lebih cepat - meskipun dengan potongan kode saya di atas, yang paling pasti tidak berarti semua. Saya menerima masalah ini mungkin terlalu tidak intuitif untuk mengganggu pada tingkat seperti itu dan akan memerlukan sesuatu yang ekstrem seperti mendekompilasi untuk benar-benar menentukan mana yang lebih baik untuk setiap situasi.
- "Apa kode iterator yang setara untuk pernyataan foreach; Saya telah melihat beberapa di internet tetapi setiap kali saya menguji mereka waktunya tidak tepat; Saya juga telah menguji beberapa iterator yang sederhana tetapi sepertinya tidak pernah mendapatkan hasil yang layak. - Apakah array iterators di PHP hanya mengerikan? " ircmaxell memberikan jawaban di bawah ini; meskipun kode mungkin hanya valid untuk versi PHP> = 5
- "Apakah ada cara / metode / konstruksi yang lebih cepat untuk beralih melalui array selain FOR / FOREACH (dan WHILE)?" Terima kasih kepada Gordon untuk jawabannya. Menggunakan tipe data baru di PHP5 akan memberikan peningkatan kinerja atau peningkatan memori (salah satunya mungkin diinginkan tergantung pada situasi Anda). Meskipun kecepatan banyak jenis baru array tampaknya tidak lebih baik daripada array (), splpriorityqueue dan splobjectstorage tampaknya jauh lebih cepat. Tautan disediakan oleh Gordon: http://matthewturland.com/2010/05/20/new-spl-features-in-php-5-3/
Terima kasih semuanya yang mencoba membantu.
Saya kemungkinan akan berpegang teguh pada foreach (versi non-referensi) untuk setiap traversal sederhana.
Jawaban:
Pendapat pribadi saya adalah menggunakan apa yang masuk akal dalam konteksnya. Secara pribadi saya hampir tidak pernah menggunakan
for
untuk array traversal. Saya menggunakannya untuk jenis iterasi lain, tetapiforeach
terlalu mudah ... Perbedaan waktu akan menjadi minimal dalam banyak kasus.Hal besar yang harus diperhatikan adalah:
Itu perulangan yang mahal, karena ia menyebut mengandalkan pada setiap iterasi tunggal. Selama Anda tidak melakukan itu, saya tidak berpikir itu benar-benar penting ...
Adapun referensi membuat perbedaan, PHP menggunakan copy-on-write, jadi jika Anda tidak menulis ke array, akan ada overhead yang relatif sedikit saat perulangan. Namun, jika Anda mulai memodifikasi array di dalam array, di situlah Anda akan mulai melihat perbedaan di antara mereka (karena orang perlu menyalin seluruh array, dan referensi dapat memodifikasi inline) ...
Adapun iterator,
foreach
setara dengan:Sejauh ada cara yang lebih cepat untuk beralih, itu benar-benar tergantung pada masalahnya. Tetapi saya benar-benar perlu bertanya, mengapa? Saya mengerti ingin membuat segalanya lebih efisien, tetapi saya pikir Anda membuang-buang waktu untuk optimasi mikro. Ingat,
Premature Optimization Is The Root Of All Evil
...Sunting: Berdasarkan komentar, saya memutuskan untuk melakukan patokan cepat ...
Dan hasilnya:
Jadi, jika Anda memodifikasi array dalam loop, beberapa kali lebih cepat untuk menggunakan referensi ...
Dan overhead hanya untuk referensi sebenarnya kurang dari menyalin array (ini pada 5.3.2) ... Jadi muncul (setidaknya 5.3.2) seolah-olah referensi secara signifikan lebih cepat ...
sumber
"the better standard way to adopt."
performance bukan satu-satunya kriteria untuk memilih apa yang akan diadopsi. terutama dalam kasus yang tidak masuk akal. Terus terang, Anda hanya membuang-buang waktuSaya tidak yakin ini sangat mengejutkan. Kebanyakan orang yang kode dalam PHP tidak berpengalaman dalam apa yang sebenarnya dilakukan PHP di bare metal. Saya akan menyatakan beberapa hal, yang sebagian besar akan benar:
Jika Anda tidak mengubah variabel, nilai tambahan lebih cepat di PHP. Ini karena referensi itu tetap dihitung dan menurut nilai memberikan lebih sedikit untuk dilakukan. Ia tahu begitu Anda memodifikasi ZVAL (struktur data internal PHP untuk sebagian besar tipe), ia harus memutusnya secara langsung (salin dan lupakan ZVAL lainnya). Tapi Anda tidak pernah memodifikasinya, jadi tidak masalah. Referensi menjadikannya lebih rumit dengan lebih banyak pembukuan yang harus dilakukan untuk mengetahui apa yang harus dilakukan ketika Anda memodifikasi variabel. Jadi, jika Anda hanya-baca, secara paradoks lebih baik bukan intinya dengan &. Saya tahu, ini berlawanan dengan intuisi, tetapi juga benar.
Foreach tidak lambat. Dan untuk iterasi sederhana, kondisi yang diuji terhadap - "apakah saya di akhir array ini" - dilakukan menggunakan kode asli, bukan opcode PHP. Bahkan jika itu opcodes yang di-cache APC, itu masih lebih lambat dari banyak operasi asli yang dilakukan di bare metal.
Menggunakan for for "for ($ i = 0; $ i <count ($ x); $ i ++) lambat karena hitungan (), dan kurangnya kemampuan PHP (atau benar-benar bahasa apa pun yang ditafsirkan) untuk mengevaluasi pada parse waktu apakah ada yang memodifikasi array. Ini mencegahnya mengevaluasi hitungan sekali.
Tetapi bahkan setelah Anda memperbaikinya dengan "$ c = hitung ($ x); untuk ($ i = 0; $ i <$ c; $ i ++) $ i <$ c adalah sekumpulan opcode Zend, seperti halnya $ i ++. Dalam perjalanan iterasi 100000, ini bisa berarti. Foreach tahu di tingkat asli apa yang harus dilakukan. Tidak perlu PHP opcodes untuk menguji kondisi "aku di akhir array ini".
Bagaimana dengan "old school" (daftar ("barang? Nah, menggunakan masing-masing (), current (), dll. Semua akan melibatkan setidaknya 1 panggilan fungsi, yang tidak lambat, tetapi tidak gratis. Ya, itu adalah PHP opcodes lagi! Jadi, sementara + daftar + masing-masing memiliki biayanya juga.
Karena alasan ini, setiap langkah dapat dimengerti merupakan pilihan terbaik untuk iterasi sederhana.
Dan jangan lupa, ini juga yang paling mudah dibaca, jadi ini win-win.
sumber
Satu hal yang harus diperhatikan dalam tolok ukur (terutama phpbench.com), adalah meskipun angkanya baik, tes tidak. Banyak tes di phpbench.com melakukan hal-hal sepele dan menyalahgunakan kemampuan PHP untuk me-cache lookup array ke condong tolok ukur atau dalam kasus iterasi pada array tidak benar-benar mengujinya dalam kasus-kasus dunia nyata (tidak ada yang menulis kosong untuk loop). Saya telah melakukan tolok ukur sendiri yang saya temukan cukup mencerminkan hasil dunia nyata dan mereka selalu menunjukkan sintaks iterasi asli bahasa yang
foreach
keluar di atas (kejutan, kejutan).sumber
Ini tahun 2020 dan banyak hal telah berkembang dengan php 7.4 dan opcache .
Berikut adalah patokan OP ^, dijalankan sebagai CLI unix , tanpa bagian gema dan html.
Tes dijalankan secara lokal di komputer biasa.
Skrip benchmark yang dimodifikasi:
Keluaran:
Seperti yang Anda lihat evolusi itu gila, sekitar 560 kali lebih cepat daripada yang dilaporkan pada 2012.
Di komputer dan server saya, mengikuti banyak percobaan saya, dasar-dasar untuk loop adalah yang tercepat. Ini bahkan lebih jelas menggunakan loop bersarang ( $ i $ j $ k ..)
Ini juga yang paling fleksibel dalam penggunaan, dan memiliki keterbacaan yang lebih baik dari pandangan saya.
sumber
Saya pikir tetapi saya tidak yakin:
for
loop membutuhkan dua operasi untuk memeriksa dan menambah nilai.foreach
memuat data dalam memori kemudian akan mengulangi setiap nilai.sumber