Penting untuk tidak membingungkan pernyataan sakelar C # dengan instruksi sakelar CIL.
Switch CIL adalah tabel lompatan, yang membutuhkan indeks ke dalam set alamat lompat.
Ini hanya berguna jika kasus C # switch berdekatan:
case 3: blah; break;
case 4: blah; break;
case 5: blah; break;
Tapi sedikit gunanya jika tidak:
case 10: blah; break;
case 200: blah; break;
case 3000: blah; break;
(Anda membutuhkan tabel ~ 3000 entri dalam ukuran, dengan hanya 3 slot yang digunakan)
Dengan ekspresi yang tidak berdekatan, kompiler dapat mulai melakukan pemeriksaan linier if-else-if-else.
Dengan set ekspresi non-berdekatan yang lebih besar, kompiler dapat mulai dengan pencarian pohon biner, dan akhirnya jika-selain-jika-lain beberapa item terakhir.
Dengan set ekspresi yang berisi rumpun item yang berdekatan, kompiler dapat mencari pohon biner, dan akhirnya beralih CIL.
Ini penuh dengan "mays" & "mights", dan itu tergantung pada kompiler (mungkin berbeda dengan Mono atau Rotor).
Saya mereplikasi hasil Anda di mesin saya menggunakan case yang berdekatan:
total waktu untuk mengeksekusi sakelar 10 arah, 10000 iterasi (ms): 25.1383
perkiraan waktu per sakelar 10 arah (ms): 0.00251383
total waktu untuk mengeksekusi switch 50 arah, 10000 iterations (ms): 26,593
perkiraan waktu per switch 50 arah (ms): 0,0026593
total waktu untuk mengeksekusi saklar 5000 arah, 10000 iterasi (ms): 23,7094
perkiraan waktu per saklar 5000 cara (ms): 0,00237094
total waktu untuk mengeksekusi switch cara 50000, 10000 iterations (ms): 20.0933
perkiraan waktu per switch cara 50000 (ms): 0.00200933
Kemudian saya juga menggunakan ekspresi kasus yang tidak berdekatan:
total waktu untuk mengeksekusi saklar 10 arah, 10000 iterations (ms): 19.6189
waktu perkiraan per saklar 10 arah (ms): 0.00196189
total waktu untuk mengeksekusi switch 500 arah, 10000 iterations (ms): 19.1664
perkiraan waktu per switch 500 arah (ms): 0.00191664
total waktu untuk mengeksekusi saklar 5000 arah, 10000 iterasi (ms): 19,5871
perkiraan waktu per saklar 5000 cara (ms): 0,00195871
Pernyataan pergantian kasus 50.000 yang tidak berbatasan tidak akan dikompilasi.
"Ekspresi terlalu panjang atau rumit untuk dikompilasi di dekat 'ConsoleApplication1.Program.Main (string [])'
Yang lucu di sini, adalah bahwa pencarian pohon biner muncul sedikit (mungkin tidak secara statistik) lebih cepat daripada instruksi sakelar CIL.
Brian, Anda telah menggunakan kata " konstan ", yang memiliki makna yang sangat pasti dari perspektif teori kompleksitas komputasi. Sementara contoh integer berdekatan sederhana dapat menghasilkan CIL yang dianggap O (1) (konstan), contoh jarang adalah O (log n) (logaritmik), contoh-contoh yang dikelompokkan terletak di suatu tempat di antara, dan contoh kecil adalah O (n) (linear) ).
Ini bahkan tidak membahas situasi String, di mana statis Generic.Dictionary<string,int32>
dapat dibuat, dan akan mengalami overhead yang pasti pada penggunaan pertama. Kinerja di sini akan tergantung pada kinerja Generic.Dictionary
.
Jika Anda memeriksa Spesifikasi Bahasa C # (bukan spesifikasi CIL), Anda akan menemukan "15.7.2 Pernyataan sakelar" tidak menyebutkan "waktu konstan" atau bahwa implementasi yang mendasarinya bahkan menggunakan instruksi sakelar CIL (berhati-hati dalam mengasumsikan hal-hal seperti).
Pada akhirnya, saklar C # terhadap ekspresi integer pada sistem modern adalah operasi sub-mikrodetik, dan biasanya tidak perlu dikhawatirkan.
Tentu saja waktu ini akan tergantung pada mesin dan kondisi. Saya tidak akan memperhatikan tes waktu ini, durasi mikrodetik yang sedang kita bicarakan dikerdilkan oleh kode "nyata" yang sedang dijalankan (dan Anda harus menyertakan beberapa "kode nyata" jika tidak, kompiler akan mengoptimalkan cabang jauh), atau jitter dalam sistem. Jawaban saya didasarkan pada penggunaan IL DASM untuk memeriksa CIL yang dibuat oleh kompiler C #. Tentu saja, ini belum final, karena instruksi aktual yang dijalankan CPU kemudian dibuat oleh JIT.
Saya telah memeriksa instruksi CPU terakhir yang benar-benar dijalankan pada mesin x86 saya, dan dapat mengonfirmasi set switch sederhana yang berdekatan melakukan sesuatu seperti:
jmp ds:300025F0[eax*4]
Di mana pencarian pohon biner penuh dengan:
cmp ebx, 79Eh
jg 3000352B
cmp ebx, 654h
jg 300032BB
…
cmp ebx, 0F82h
jz 30005EEE