Versi panjang ...
Seorang rekan kerja menegaskan hari ini setelah melihat penggunaan saya while (1)
dalam skrip Perl yang for (;;)
lebih cepat. Saya berpendapat bahwa mereka harus sama berharap bahwa juru bahasa akan mengoptimalkan perbedaan. Saya membuat skrip yang menjalankan 1.000.000.000 untuk iterasi loop dan jumlah yang sama saat loop dan mencatat waktu antara. Saya tidak dapat menemukan perbedaan yang berarti. Rekan kerja saya mengatakan bahwa seorang profesor telah memberi tahu dia bahwa yang while (1)
melakukan perbandingan 1 == 1
dan yang for (;;)
tidak. Kami mengulangi tes yang sama dengan 100x jumlah iterasi dengan C ++ dan perbedaannya dapat diabaikan. Namun itu adalah contoh grafik tentang seberapa cepat kode terkompilasi dapat dibandingkan dengan bahasa scripting.
Versi pendek...
Apakah ada alasan untuk memilih while (1)
lebih daripada for (;;)
jika Anda membutuhkan loop tak terbatas untuk keluar?
Catatan: Jika tidak jelas dari pertanyaan. Ini murni diskusi akademik yang menyenangkan antara beberapa teman. Saya sadar ini bukan konsep super penting yang harus dipikirkan oleh semua programmer. Terima kasih atas semua jawaban hebat yang saya (dan saya yakin orang lain) telah pelajari beberapa hal dari diskusi ini.
Pembaruan: Rekan kerja yang disebutkan di atas menimbang dengan tanggapan di bawah ini.
Dikutip di sini kalau-kalau itu akan dimakamkan.
Itu datang dari programmer AMD assembly. Dia menyatakan bahwa programmer C (poeple) tidak menyadari bahwa kode mereka memiliki inefisiensi. Dia mengatakan hari ini, kompiler gcc sangat bagus, dan membuat orang seperti dia keluar dari bisnis. Dia mengatakan misalnya, dan bercerita tentang
while 1
vsfor(;;)
. Saya menggunakannya sekarang karena kebiasaan tetapi gcc dan terutama interpreter akan melakukan operasi yang sama (lompatan prosesor) untuk kedua hari ini, karena mereka dioptimalkan.
sumber
Jawaban:
Pada perl, mereka menghasilkan opcode yang sama:
Demikian juga dalam GCC:
Jadi saya kira jawabannya adalah, mereka sama dalam banyak kompiler. Tentu saja, untuk beberapa kompiler lain ini mungkin tidak selalu demikian, tetapi kemungkinan kode di dalam loop akan menjadi beberapa ribu kali lebih mahal daripada loop itu sendiri, jadi siapa yang peduli?
sumber
Dengan menggunakan GCC, keduanya sepertinya dikompilasi dengan bahasa assembly yang sama:
sumber
Tidak ada banyak alasan untuk memilih satu dari yang lain. Saya pikir itu
while(1)
dan terutamawhile(true)
lebih mudah dibaca daripadafor(;;)
, tapi itu hanya preferensi saya.sumber
forever
itu token sendiri.Tidak ada perbedaan menurut standar. 6.5.3 / 1 memiliki:
Dan 6.5.3 / 2 memiliki:
Jadi menurut standar C ++ kode:
persis sama dengan:
sumber
Kompiler Visual C ++ digunakan untuk memancarkan peringatan
(Ekspresi konstan) tetapi tidak untuk
Saya telah melanjutkan praktik lebih memilih
for (;;)
untuk alasan itu, tetapi saya tidak tahu apakah kompiler masih melakukannya hari ini.sumber
for(;;)
adalah satu karakter yang kurang untuk mengetik jika Anda ingin pergi ke arah itu untuk mengoptimalkan hal-hal.sumber
Turbo C dengan kompiler lama ini
for(;;)
menghasilkan kode yang lebih cepatwhile(1)
.Hari ini gcc, Visual C (saya pikir hampir semua) kompiler mengoptimalkan dengan baik, dan CPU dengan 4,7 MHz jarang digunakan.
Pada hari-hari
for( i=10; i; i-- )
itu lebih cepat daripadafor( i=1; i <=10; i++ )
, karena perbandingannyai
adalah 0, menghasilkan lompatan bersyarat CPU-Zero-Flag. Dan Zero-Flag telah dimodifikasi dengan operasi pengurangan terakhir( i-- )
, tidak diperlukan operasi cmp tambahan.dan di sini dengan
for(i=1; i<=10; i++)
cmpl tambahan:sumber
Untuk semua orang yang berdebat Anda tidak boleh menggunakan indefinte while loop, dan menyarankan hal-hal gila seperti menggunakan open goto (serius, aduh)
Tidak bisa diwakili secara efektif dengan cara lain. Bukan tanpa membuat variabel keluar dan melakukan sihir hitam agar tetap disinkronkan.
Jika Anda memiliki kecenderungan untuk sintaks yang lebih goto-esque, gunakan sesuatu yang waras yang membatasi ruang lingkup.
Akhirnya Kecepatan tidak begitu penting
Mengkhawatirkan tentang seberapa efektif kecepatan membangun looping yang berbeda adalah buang-buang waktu. Optimalisasi prematur melalui dan melalui. Saya tidak bisa memikirkan situasi apa pun yang pernah saya lihat di mana kode profil menemukan kemacetan dalam pilihan saya membangun perulangan.
Umumnya bagaimana loop dan bagaimana loop.
Anda harus "mengoptimalkan" agar mudah dibaca dan ringkas, dan menulis apa pun yang terbaik untuk menjelaskan masalah kepada pengisap miskin berikutnya yang menemukan kode Anda.
Jika Anda menggunakan trik "goto LABEL" yang disebutkan oleh seseorang, dan saya harus menggunakan kode Anda, bersiaplah untuk tidur dengan satu mata terbuka, terutama jika Anda melakukannya lebih dari sekali, karena hal-hal semacam itu menciptakan kode spageti yang mengerikan .
Hanya karena Anda dapat membuat kode spaghetti bukan berarti Anda harus melakukannya
sumber
Dari Stroustrup, TC ++ PL (edisi ke-3), §6.1.1:
Saya lebih suka
for (;;)
.sumber
Jika kompiler tidak melakukan optimasi apa pun,
for(;;)
akan selalu lebih cepat daripadawhile(true)
. Ini karena sementara-pernyataan mengevaluasi kondisi setiap saat, tetapi untuk-pernyataan adalah lompatan tanpa syarat. Tetapi jika kompiler mengoptimalkan aliran kontrol, ia dapat menghasilkan beberapa opcode. Anda dapat membaca kode pembongkaran dengan sangat mudah.PS Anda bisa menulis loop tak terbatas seperti ini:
sumber
Saya pernah mendengar tentang ini sekali.
Itu datang dari programmer AMD assembly. Dia menyatakan bahwa programmer C (orang-orang) tidak menyadari bahwa kode mereka memiliki inefisiensi. Dia mengatakan hari ini, kompiler gcc sangat bagus, dan membuat orang seperti dia keluar dari bisnis. Dia mengatakan misalnya, dan bercerita tentang
while 1
vsfor(;;)
. Saya menggunakannya sekarang karena kebiasaan tetapi gcc dan terutama interpreter akan melakukan operasi yang sama (lompatan prosesor) untuk kedua hari ini, karena mereka dioptimalkan.sumber
Dalam versi bahasa kompilasi yang dioptimalkan, seharusnya tidak ada perbedaan yang berarti antara keduanya. Seharusnya keduanya tidak melakukan perbandingan saat runtime, mereka hanya akan mengeksekusi kode loop sampai Anda keluar dari loop secara manual (misalnya dengan a
break
).sumber
Saya terkejut bahwa tidak ada yang diuji dengan benar
for (;;)
dibandingkanwhile (1)
di perl!Karena perl adalah bahasa yang diinterpretasikan, waktu untuk menjalankan skrip perl tidak hanya terdiri dari fase eksekusi (yang dalam hal ini sama) tetapi juga fase interpretasi sebelum eksekusi. Kedua fase ini harus diperhitungkan saat melakukan perbandingan kecepatan.
Untungnya perl memiliki modul Benchmark yang nyaman yang dapat kita gunakan untuk mengimplementasikan benchmark seperti berikut:
Perhatikan bahwa saya menguji dua versi berbeda dari loop tak terbatas: satu yang lebih pendek dari loop sementara dan satu lagi yang memiliki ruang ekstra untuk membuatnya panjang sama dengan loop sementara.
Di Ubuntu 11.04 x86_64 dengan perl 5.10.1 saya mendapatkan hasil berikut:
Loop sementara jelas merupakan pemenang di platform ini.
Pada FreeBSD 8.2 x86_64 dengan perl 5.14.1:
Sedangkan loop adalah pemenangnya juga di sini.
Pada FreeBSD 8.2 i386 dengan perl 5.14.1:
Secara mengejutkan for for dengan ruang tambahan adalah pilihan tercepat di sini!
Kesimpulan saya adalah bahwa while loop harus digunakan pada platform x86_64 jika programmer mengoptimalkan kecepatan. Jelas a for loop harus digunakan ketika mengoptimalkan ruang. Sayangnya hasil saya tidak dapat disimpulkan tentang platform lain.
sumber
Benchmark
memiliki keterbatasan dan tidak dapat digunakan untuk membedakan cepat dari lambat jika hasilnya berada dalam jarak 7% satu sama lain. Selain itu, Anda belum menguji perbedaan antarafor
danwhile
loop karena setiap sub akandie
sebelum mencapai loop sendiri. Dan sejak kapan jumlah spasi putih bagi penerjemah Perl? Maaf, tetapi analisisnya sangat cacat.die
Ada di kode saya karena niat saya adalah untuk menguji hanya perbedaan waktu kompilasi . Seperti orang lain telah menunjukkan kode byte yang dihasilkan adalah identik, sehingga tidak ada gunanya menguji itu. Secara mengejutkan jumlah ruang putih tampaknya membuat perbedaan kecil dalam hal ini di lingkungan pengujian saya. Mungkin ada hubungannya dengan bagaimana karakter akhirnya bisa selaras dalam memori atau sesuatu yang serupa ...Benchmark
tidak meyakinkan. Jangan percaya perbedaan 1% sama sekali!-60
menjalankan tes selama 60 detik.Secara teori, kompiler yang sepenuhnya naif dapat menyimpan literal '1' dalam biner (ruang pemborosan) dan memeriksa untuk melihat apakah 1 == 0 setiap iterasi (membuang-buang waktu dan lebih banyak ruang).
Namun pada kenyataannya, bahkan dengan optimisasi "tidak", kompiler masih akan mengurangi keduanya menjadi sama. Mereka juga dapat memancarkan peringatan karena bisa menunjukkan kesalahan logis. Misalnya, argumen dari
while
dapat didefinisikan di tempat lain dan Anda tidak menyadari itu konstan.sumber
Saya terkejut tidak ada yang menawarkan bentuk yang lebih langsung, sesuai dengan perakitan yang diinginkan:
sumber
{ forever: do stuff; goto forever; }
)while(1)
adalah ungkapanfor(;;)
yang diakui oleh sebagian besar penyusun.Saya senang melihat perl mengakui
until(0)
juga.sumber
Untuk meringkas perdebatan
for (;;)
vswhile (1)
jelas bahwa yang pertama lebih cepat pada hari-hari kompiler tidak mengoptimalkan yang lebih lama, itu sebabnya Anda cenderung melihatnya di basis kode yang lebih lama seperti komentar kode Lions Unix Source, namun di era badass mengoptimalkan kompiler keuntungan tersebut dioptimalkan jauh ditambah dengan fakta bahwa yang terakhir lebih mudah dipahami daripada yang sebelumnya saya percaya bahwa itu akan lebih disukai.sumber
Baru saja menemukan utas ini (meskipun terlambat beberapa tahun).
Saya pikir saya menemukan alasan sebenarnya mengapa "untuk (;;)" lebih baik daripada "sementara (1)".
sesuai dengan "standar pengkodean barr 2018"
pada dasarnya, ini bukan masalah kecepatan tetapi masalah keterbacaan. Bergantung pada font / cetak kode nomor satu (1) untuk sementara waktu mungkin terlihat seperti huruf kecil l.
yaitu 1 vs l. (dalam beberapa font ini terlihat identik).
Jadi sementara (1) mungkin terlihat seperti beberapa while tergantung pada variabel huruf L.
sementara (benar) mungkin juga bekerja tetapi dalam beberapa kasus C yang lama dan tertanam C benar / salah belum didefinisikan kecuali stdbool.h disertakan.
sumber
l
, bukan itu1
danl
dapat terlihat serupa.Saya akan berpikir bahwa keduanya sama dalam hal kinerja. Tapi saya lebih suka sementara (1) untuk keterbacaan tetapi saya mempertanyakan mengapa Anda membutuhkan loop tak terbatas.
sumber
Mereka sama. Ada banyak pertanyaan yang lebih penting untuk direnungkan.
Maksud saya yang tersirat tetapi tidak secara eksplisit dibuat di atas, adalah bahwa kompiler yang layak akan menghasilkan kode yang sama persis untuk kedua bentuk loop. Poin yang lebih besar adalah bahwa konstruksi perulangan adalah bagian kecil dari waktu berjalan dari algoritma apa pun, dan Anda harus terlebih dahulu memastikan bahwa Anda telah mengoptimalkan algoritma dan segala sesuatu yang berkaitan dengannya. Mengoptimalkan konstruksi lingkaran Anda harus benar-benar di bagian bawah daftar prioritas Anda.
sumber