Seberapa mahal refleksi NET?

210

Saya terus-menerus mendengar betapa buruknya refleksi yang digunakan. Sementara saya umumnya menghindari refleksi dan jarang menemukan situasi di mana tidak mungkin untuk menyelesaikan masalah saya tanpanya, saya bertanya-tanya ...

Bagi mereka yang telah menggunakan refleksi dalam aplikasi, sudahkah Anda mengukur hit kinerja dan, apakah itu benar-benar buruk?

Dan Herbert
sumber
Anda mungkin juga ingin memeriksa pertanyaan ini. stackoverflow.com/questions/224232/…
smaclell
1
Gunakan api di fastflect.codeplex.com. Ini akan mempercepat refleksi sebanyak 500x untuk getter / setter / invokers dan beberapa hal lainnya. Sumber dan info tentang cara kerjanya juga ada di sana jika Anda perlu memperpanjangnya.
Brandon Moore
3
Bagaimana info ini dilihat pada tahun 2014? Adakah yang berubah dalam 4 tahun ini?
Arnthor
1
Tugas sederhana untuk menetapkan nilai ke properti instance kira-kira 150 kali lebih lambat melakukannya dengan refleksi (PropertyInfo.SetValue (instance, value)) daripada dengan coding langsung (instance.property = nilai) Ini dalam .NET 4.0
Thanasis Ioannidis

Jawaban:

130

Ini. Tetapi itu tergantung pada apa yang Anda coba lakukan.

Saya menggunakan refleksi untuk memuat majelis (plugins) secara dinamis dan kinerjanya "penalti" bukan masalah, karena operasi adalah sesuatu yang saya lakukan saat startup aplikasi.

Namun, jika Anda merefleksikan di dalam serangkaian loop bersarang dengan masing-masing panggilan refleksi, saya katakan Anda harus meninjau kembali kode Anda :)

Untuk operasi "beberapa waktu", refleksi dapat diterima dan Anda tidak akan melihat adanya keterlambatan atau masalah dengannya. Ini adalah mekanisme yang sangat kuat dan bahkan digunakan oleh .NET, jadi saya tidak mengerti mengapa Anda tidak mencobanya.

Martin Marconcini
sumber
Saya telah menggunakan refleksi untuk mendapatkan metode, nama kelas dari metode saat ini untuk mencatat kesalahan dalam try-catch. pada dasarnya untuk menghindari hardcoding nama fungsi saat kesalahan logging. Apakah saya perlu khawatir?
Sangram Nandkhile
@Sangram tidak, tidak apa
Karthik AMR
@Sangram no, kecuali jika Anda memiliki banyak kesalahan yang mengharuskan penangkapan terus-menerus, yang kemudian akan menjadi masalah yang berbeda :)
Martin Marconcini
5
@Sangram, sementara kinerja refleksi seharusnya tidak menjadi masalah dalam kasus Anda, sepertinya Anda mencoba menerapkan kembali apa yang sudah ada, pengecualian lama dengan cara yang jauh lebih elegan di luar kotak ...
Jacek Gorgoń
152

Dalam ceramahnya The Performance of Everyday Things , Jeff Richter menunjukkan bahwa memanggil metode dengan refleksi sekitar 1000 kali lebih lambat daripada memanggilnya secara normal.

Kiat Jeff: jika Anda perlu memanggil metode beberapa kali, gunakan refleksi sekali untuk menemukannya, kemudian tetapkan ke delegasi , dan kemudian panggil delegasi.

ESRogs
sumber
18
Saya telah menghadiri Devscovery juga, dan setuju dengan hasil ini untuk .NET 3.5. Mengkompilasi ulang program benchmark kinerja Devscovery untuk .NET 4 menunjukkan peningkatan besar-besaran! Biaya turun menjadi 100 kali lebih lambat. Menggunakan refleksi untuk typeof () lookup tidak berubah antara. NET 3.5 dan .NET 4.
John Wigger
61

Kinerja pantulan akan tergantung pada implementasinya (panggilan berulang harus di-cache misalnya:) entity.GetType().GetProperty("PropName"). Karena sebagian besar refleksi yang saya lihat sehari-hari digunakan untuk mengisi entitas dari pembaca data atau struktur tipe repositori lainnya, saya memutuskan untuk membandingkan kinerja secara spesifik pada refleksi ketika digunakan untuk mendapatkan atau mengatur properti objek.

Saya menyusun tes yang saya anggap adil karena cache semua panggilan berulang dan hanya kali panggilan SetValue atau GetValue yang sebenarnya. Semua kode sumber untuk tes kinerja dalam bitbucket di: https://bitbucket.org/grenade/accessortest . Pengawasan disambut dan didorong.

Kesimpulan yang saya dapatkan adalah bahwa itu tidak praktis dan tidak memberikan peningkatan kinerja yang nyata untuk menghapus refleksi dalam lapisan akses data yang mengembalikan kurang dari 100.000 baris pada saat implementasi refleksi dilakukan dengan baik.

Grafik waktu (y) terhadap jumlah entitas yang dihuni (x)

Grafik di atas menunjukkan output tolok ukur kecil saya dan menunjukkan bahwa mekanisme yang mengungguli refleksi, hanya terlihat jelas setelah tanda 100.000 siklus. Kebanyakan DAL hanya mengembalikan beberapa ratus atau mungkin ribuan baris sekaligus dan pada level ini refleksi berfungsi dengan baik.

granat
sumber
9
Belum tentu. Konversi DAL Anda mungkin hanya pada beberapa ribu item, tetapi kalikan dengan pengguna bersamaan menggunakan aplikasi Anda (jika itu web) dan itu mungkin bertambah seperti jika Anda mengonversi jutaan item. Jika metode tertentu 100 kali lebih lambat akan jauh lebih lambat pada set kecil dan besar. Lebih lambat lebih lambat.
Robert Koritnik
@RobertKoritnik Itu dengan asumsi bahwa metode web pada server Anda tidak Asinkron
Kurren
@kurren asynchronicity tidak memengaruhi refleksi melainkan sumber daya server. Metode Asynchronous Web tentu saja akan dapat melayani lebih banyak pengguna, tetapi refleksi masih akan lambat. Dan refleksi dengan sendirinya AFAIK adalah proses yang sinkron. Di sisi lain, pengambilan data akan menjadi satu-satunya bagian yang akan bermain dengan baik dengan desain asinkron.
Robert Koritnik
3
Apa metode Hyper pada grafik? Apa bedanya dengan Reflector?
Bryan Legend
14

Jika Anda tidak berada dalam satu lingkaran, jangan khawatir.

David Plumpton
sumber
12

Pengalaman saya yang paling relevan adalah menulis kode untuk membandingkan setiap dua entitas data dari tipe yang sama dalam model objek besar. Membuatnya berhasil, mencobanya, berlari seperti anjing, jelas.

Saya sedih, kemudian dalam semalam menyadari bahwa tanpa mengubah logika, saya bisa menggunakan algoritma yang sama untuk menghasilkan metode secara otomatis untuk melakukan perbandingan tetapi secara statis mengakses properti. Tidak butuh waktu sama sekali untuk mengadaptasi kode untuk tujuan ini dan saya memiliki kemampuan untuk melakukan perbandingan properti yang mendalam dengan entitas dengan kode statis yang dapat diperbarui dengan mengklik tombol setiap kali model objek berubah.

Maksud saya adalah: Dalam percakapan dengan kolega karena saya telah beberapa kali menunjukkan bahwa penggunaan refleksi mereka bisa untuk membuat kode secara otomatis untuk mengkompilasi daripada melakukan operasi runtime dan ini sering layak dipertimbangkan.

Gaz
sumber
Menimbang bahwa Visual Studio memiliki dukungan template yang sangat baik, itu adalah cara praktis untuk menggunakan pembuatan kode
Sebastian
12

Tidak secara besar-besaran. Saya tidak pernah memiliki masalah dengan itu dalam pengembangan desktop kecuali, seperti Martin menyatakan, Anda menggunakannya di lokasi yang konyol. Saya telah mendengar banyak orang memiliki ketakutan yang sama sekali tidak rasional tentang kinerjanya dalam pengembangan desktop.

Dalam Compact Framework (yang biasanya saya ikuti), itu cukup banyak kutukan dan harus dihindari seperti wabah dalam banyak kasus. Saya masih jarang bisa menggunakannya, tetapi saya harus sangat berhati-hati dengan penerapannya yang jauh lebih tidak menyenangkan. :(

Berdalih
sumber
5
+1 untuk mengajari saya kata baru: laknat. Juga untuk menyebutkan ketakutan irasional. Saya takut programmer yang takut tidak rasional - itu menunjukkan bahwa mereka tidak benar-benar tahu apa yang mereka lakukan dan hanya mendasarkan apa yang mereka lakukan pada apa yang orang lain katakan kepada mereka. cough cargo cult cough
bsneeze
1
Ahhhh Cargo Cult. Sekarang ada contoh bagus tentang perilaku manusia yang penasaran.
Quibblesome
10

Sudah cukup buruk bahwa Anda harus khawatir bahkan tentang refleksi yang dilakukan secara internal oleh .NET libraries untuk kode kritis kinerja.

Contoh berikut sudah usang - benar pada saat itu (2008), tetapi lama diperbaiki dalam versi CLR yang lebih baru. Refleksi secara umum masih merupakan hal yang agak mahal!

Contoh kasus: Anda tidak boleh menggunakan anggota yang dinyatakan sebagai "Objek" dalam pernyataan kunci (C #) / SyncLock (VB.NET) dalam kode kinerja tinggi. Mengapa? Karena CLR tidak dapat mengunci pada tipe nilai, yang berarti ia harus melakukan pemeriksaan tipe run-time untuk melihat apakah Objek Anda sebenarnya tipe nilai dan bukan tipe referensi.

McKenzieG1
sumber
13
Agar adil, pemeriksaan jenis refleksi cepat.
Jimmy
1
Untuk 'kode kritis kinerja' seperti itu, apakah Anda harus benar-benar menggunakan .NET?
Seph
1
@Seph: Bagian dinamis / refleksi dari .NET, no. Tapi biasanya C # /. NET, mengapa tidak? C ++ vs C # speedups marjinal di lapisan aplikasi (C ++ masih beberapa% lebih cepat pada rutinitas matematika intensif). Dan saya kira Anda tidak menyarankan perakitan ...
DeepSpace101
Jenis nilai kotak (mis. Objek) dapat dikunci. @BryceWagner benar.
Fowl
1
Agar adil (bagi saya), lebih akurat untuk mengatakan bahwa jawabannya "usang", daripada "omong kosong". Komentar saya tentang perilaku kunci (obj) sudah akurat pada saat itu ditulis, tetapi perilaku implementasi-spesifik dari CLR sudah lama hilang.
McKenzieG1
5

Seperti halnya semua hal dalam pemrograman Anda harus menyeimbangkan biaya kinerja dengan manfaat apa pun yang diperoleh. Refleksi adalah alat yang sangat berharga ketika digunakan dengan hati-hati. Saya membuat perpustakaan pemetaan O / R di C # yang menggunakan refleksi untuk melakukan binding. Ini bekerja dengan sangat baik. Sebagian besar kode refleksi hanya dieksekusi satu kali, sehingga kinerja yang dicapai cukup kecil, tetapi manfaatnya sangat besar. Jika saya menulis algoritma pengurutan fandangled baru, saya mungkin tidak akan menggunakan refleksi, karena mungkin akan skala buruk.

Saya menghargai bahwa saya belum menjawab pertanyaan Anda di sini. Maksud saya adalah itu tidak terlalu penting. Gunakan refleksi jika sesuai. Ini hanyalah fitur bahasa lain yang perlu Anda pelajari bagaimana dan kapan menggunakannya.

Mike Thompson
sumber
3

Refleksi dapat memiliki dampak nyata pada kinerja jika Anda menggunakannya untuk pembuatan objek yang sering. Saya telah mengembangkan aplikasi berdasarkan Blok Aplikasi UI Komposit yang sangat mengandalkan refleksi. Ada penurunan kinerja yang nyata terkait dengan pembuatan objek melalui refleksi.

Namun dalam kebanyakan kasus tidak ada masalah dengan penggunaan refleksi. Jika Anda hanya perlu memeriksa beberapa perakitan, saya akan merekomendasikan Mono.Cecil yang sangat ringan dan cepat

aku
sumber
3

Refleksi mahal karena banyak pemeriksaan yang harus dilakukan runtime setiap kali Anda membuat permintaan untuk metode yang cocok dengan daftar parameter. Di suatu tempat jauh di dalam, ada kode yang mengitari semua metode untuk suatu jenis, memverifikasi visibilitasnya, memeriksa jenis kembali dan juga memeriksa jenis masing-masing dan setiap parameter. Semua ini membutuhkan waktu.

Ketika Anda menjalankan metode itu secara internal ada beberapa kode yang melakukan hal-hal seperti memeriksa Anda melewati daftar parameter yang kompatibel sebelum menjalankan metode target yang sebenarnya.

Jika mungkin selalu disarankan agar satu cache menangani metode jika seseorang akan terus menggunakannya kembali di masa depan. Seperti semua tip pemrograman yang baik, seringkali masuk akal untuk menghindari pengulangan. Dalam hal ini akan sia-sia untuk terus mencari metode dengan parameter tertentu dan kemudian menjalankannya setiap waktu.

Lihat-lihat sumber dan lihat apa yang sedang dilakukan.

mP.
sumber
3

Seperti halnya segalanya, ini semua tentang menilai situasi. Di DotNetNuke ada komponen inti yang disebut FillObjectyang menggunakan refleksi untuk mengisi objek dari flatows.

Ini adalah skenario yang cukup umum dan ada artikel di MSDN, Menggunakan Refleksi untuk Mengikat Objek Bisnis ke ASP.NET Form Controls yang mencakup masalah kinerja.

Selain kinerja, satu hal yang saya tidak suka tentang menggunakan refleksi dalam skenario tertentu adalah bahwa ia cenderung mengurangi kemampuan untuk memahami kode sekilas yang bagi saya sepertinya tidak sepadan dengan usaha ketika Anda menganggap Anda juga kehilangan kompilasi keamanan waktu sebagai lawan dataset sangat diketik atau sesuatu seperti LINQ ke SQL .

lomaxx
sumber
2

Refleksi tidak secara drastis memperlambat kinerja aplikasi Anda. Anda mungkin dapat melakukan hal-hal tertentu lebih cepat dengan tidak menggunakan refleksi, tetapi jika Refleksi adalah cara termudah untuk mencapai beberapa fungsi, maka gunakanlah. Anda selalu dapat memperbaiki kode Anda dari Refleksi jika itu menjadi masalah kinerja.

Chris Pietschmann
sumber
1

Saya pikir Anda akan menemukan bahwa jawabannya adalah, itu tergantung. Ini bukan masalah besar jika Anda ingin memasukkannya ke dalam aplikasi daftar tugas Anda. Ini adalah masalah besar jika Anda ingin meletakkannya di perpustakaan kegigihan Facebook.

tsimon
sumber