Banyak buku Java yang menggambarkan switch
pernyataan itu lebih cepat daripada if else
pernyataan itu. Tetapi saya tidak menemukan di mana pun mengapa peralihan lebih cepat daripada jika .
Contoh
Saya memiliki situasi saya harus memilih satu dari dua item. Saya bisa menggunakan keduanya
switch (item) {
case BREAD:
//eat Bread
break;
default:
//leave the restaurant
}
atau
if (item == BREAD) {
//eat Bread
} else {
//leave the restaurant
}
mempertimbangkan item dan ROTI adalah nilai int konstan.
Dalam contoh di atas, mana yang lebih cepat beraksi dan mengapa?
java
switch-statement
Jacob van Lingen
sumber
sumber
Jawaban:
Karena ada bytecode khusus yang memungkinkan evaluasi pernyataan saklar efisien ketika ada banyak kasus.
Jika diimplementasikan dengan pernyataan IF Anda akan memiliki cek, lompatan ke klausa berikutnya, cek, lompat ke klausa berikutnya dan seterusnya. Dengan sakelar, JVM memuat nilai untuk membandingkan dan mengulangi tabel nilai untuk menemukan kecocokan, yang lebih cepat dalam banyak kasus.
sumber
switch
tidak boleh diterjemahkan ke dalamtableswitch
instruksi bytecode - ini bisa menjadilookupswitch
instruksi yang bekerja serupa dengan if / else (ii) bahkantableswitch
instruksi bytecode dapat dikompilasi menjadi serangkaian if / else oleh JIT, tergantung pada faktor seperti jumlahcase
s.tableswitch
vsloopuswitch
: stackoverflow.com/questions/10287700/…Sebuah
switch
pernyataan tidak selalu lebih cepat daripadaif
pernyataan. Ini berskala lebih baik daripada daftar panjangif-else
pernyataan karenaswitch
dapat melakukan pencarian berdasarkan semua nilai. Namun, untuk kondisi yang singkat tidak akan lebih cepat dan bisa lebih lambat.sumber
switch
akan lebih jelas jika tidak lebih cepat.JVM saat ini memiliki dua jenis kode byte switch: LookupSwitch dan TableSwitch.
Setiap kasus dalam pernyataan switch memiliki offset integer, jika offset ini berdekatan (atau sebagian besar bersebelahan tanpa celah besar) (kasus 0: kasus 1: kasus 2, dll.), Maka TableSwitch digunakan.
Jika offset tersebar dengan celah yang besar (kasus 0: kasus 400: kasus 93748 :, dll.), Maka LookupSwitch digunakan.
Singkatnya, perbedaannya adalah bahwa TableSwitch dilakukan dalam waktu yang konstan karena setiap nilai dalam rentang nilai yang mungkin diberikan offset kode byte tertentu. Jadi, saat Anda memberikan pernyataan offset 3, ia tahu untuk melompat ke depan 3 untuk menemukan cabang yang benar.
Switch pencarian menggunakan pencarian biner untuk menemukan cabang kode yang benar. Ini berjalan dalam waktu O (log n), yang masih bagus, tapi bukan yang terbaik.
Untuk informasi lebih lanjut tentang ini, lihat di sini: Perbedaan antara JVM LookupSwitch dan TableSwitch?
Sejauh mana yang tercepat, gunakan pendekatan ini: Jika Anda memiliki 3 kasus atau lebih yang nilainya berurutan atau hampir berurutan, selalu gunakan sakelar.
Jika Anda memiliki 2 kasus, gunakan pernyataan if.
Untuk situasi lain, peralihan kemungkinan besar lebih cepat, tetapi itu tidak dijamin, karena pencarian biner di LookupSwitch dapat mencapai skenario yang buruk.
Juga, perlu diingat bahwa JVM akan menjalankan pengoptimalan JIT pada pernyataan if yang akan mencoba menempatkan cabang terpanas terlebih dahulu dalam kode. Ini disebut "Prediksi Cabang". Untuk informasi lebih lanjut tentang ini, lihat di sini: https://dzone.com/articles/branch-prediction-in-java
Pengalaman Anda mungkin berbeda. Saya tidak tahu bahwa JVM tidak menjalankan pengoptimalan serupa di LookupSwitch, tetapi saya telah belajar untuk mempercayai pengoptimalan JIT dan tidak mencoba mengakali kompiler.
sumber
switch
fitur bahasa yang lebih kuat. Pencocokan pola, misalnya, akan memungkinkan pencarian yang lebih lancar dan berperformainstanceof
. Namun, menurut saya aman untuk mengasumsikan bahwa untuk skenario switch / if dasar, aturan yang saya sebutkan akan tetap berlaku.Jadi jika Anda berencana untuk memiliki banyak paket memori tidak terlalu mahal hari ini dan arraynya cukup cepat. Anda juga tidak dapat mengandalkan pernyataan switch untuk membuat tabel lompat secara otomatis sehingga lebih mudah untuk membuat sendiri skenario tabel lompat. Seperti yang Anda lihat pada contoh di bawah ini, kami mengasumsikan maksimal 255 paket.
Untuk mendapatkan hasil di bawah ini Anda perlu abstraksi .. saya tidak akan menjelaskan cara kerjanya jadi semoga Anda memiliki pemahaman tentang itu.
Saya memperbarui ini untuk mengatur ukuran paket menjadi 255 jika Anda membutuhkan lebih dari itu Anda harus melakukan pemeriksaan batas untuk (id <0) || (id> length).
Edit karena saya sering menggunakan Jump Table di C ++ sekarang saya akan menunjukkan contoh tabel lompat fungsi pointer. Ini adalah contoh yang sangat umum, tetapi saya telah menjalankannya dan berfungsi dengan benar. Perlu diingat Anda harus mengatur pointer ke NULL, C ++ tidak akan melakukan ini secara otomatis seperti di Java.
Hal lain yang ingin saya kemukakan adalah Divide and Conquer yang terkenal. Jadi ide array saya di atas 255 dapat dikurangi menjadi tidak lebih dari 8 pernyataan if sebagai skenario kasus terburuk.
Yaitu tetapi perlu diingat itu menjadi berantakan dan sulit untuk dikelola dengan cepat dan pendekatan saya yang lain umumnya lebih baik, tetapi ini digunakan dalam kasus di mana array tidak akan memotongnya. Anda harus mencari tahu kasus penggunaan Anda dan kapan setiap situasi bekerja paling baik. Sama seperti Anda tidak ingin menggunakan salah satu dari pendekatan ini jika Anda hanya memiliki sedikit pemeriksaan.
sumber
0 <= id < packets.length
dan memastikanpackets[id]!=null
dan kemudian melakukannyapackets[id].execute(data)
?Pada tingkat bytecode, variabel subjek dimuat hanya sekali ke register prosesor dari alamat memori dalam file .class terstruktur yang dimuat oleh Runtime, dan ini ada dalam pernyataan switch; sedangkan dalam pernyataan-if, instruksi jvm yang berbeda dihasilkan oleh DE kompilasi kode Anda, dan ini mengharuskan setiap variabel dimuat ke dalam register meskipun variabel yang sama digunakan seperti pada pernyataan-if berikutnya. Jika Anda tahu tentang pengkodean dalam bahasa assembly maka ini akan menjadi hal biasa; meskipun java compiled cox bukan bytecode, atau kode mesin langsung, konsep kondisionalnya masih konsisten. Nah, saya mencoba menghindari teknis yang lebih dalam saat menjelaskan. Saya harap saya telah membuat konsep itu jelas dan tersingkap. Terima kasih.
sumber