Kita tahu mahal untuk menangkap pengecualian. Tapi, apakah terlalu mahal untuk menggunakan blok try-catch di Jawa bahkan jika pengecualian tidak pernah dilontarkan?
Saya menemukan pertanyaan / jawaban Stack Overflow. Mengapa coba blok mahal? , tetapi untuk .NET .
java
performance
try-catch
jsedano
sumber
sumber
try { /* do stuff */ } finally { /* make sure to release resources */ }
legal dan bermanfaatfinally
blok menggunakantry-with-resources
Jawaban:
try
hampir tidak ada biaya sama sekali. Alih-alih melakukan pekerjaan menyiapkantry
saat runtime, metadata kode ini disusun pada waktu kompilasi sehingga ketika pengecualian dilemparkan, sekarang melakukan operasi yang relatif mahal berjalan menumpuk dan melihat apakah adatry
blok yang akan menangkap ini pengecualian. Dari sudut pandang orang awam,try
mungkin juga gratis. Ini sebenarnya membuang pengecualian yang dikenakan biaya - tetapi kecuali Anda melempar ratusan atau ribuan pengecualian, Anda tetap tidak akan menyadari biayanya.try
memiliki beberapa biaya kecil yang terkait dengannya. Java tidak dapat melakukan beberapa optimasi pada kode ditry
blok yang seharusnya dilakukan. Sebagai contoh, Java akan sering mengatur ulang instruksi dalam suatu metode untuk membuatnya berjalan lebih cepat - tetapi Java juga perlu menjamin bahwa jika pengecualian dilemparkan, eksekusi metode diamati seolah-olah pernyataannya, sebagaimana ditulis dalam kode sumber, dieksekusi untuk beberapa baris.Karena dalam
try
blok pengecualian dapat dilempar (pada baris apa pun di blok coba! Beberapa pengecualian dilemparkan secara tidak serempak, seperti dengan memanggilstop
Thread (yang sudah usang), dan bahkan selain itu OutOfMemoryError dapat terjadi hampir di mana saja) dan belum dapat ditangkap dan kode terus dieksekusi setelah itu dalam metode yang sama, lebih sulit untuk alasan tentang optimasi yang dapat dilakukan, sehingga mereka cenderung terjadi. (Seseorang harus memprogram kompiler untuk melakukannya, alasan dan menjamin kebenaran, dll. Ini akan sangat menyusahkan untuk sesuatu yang berarti 'luar biasa') Tapi sekali lagi, dalam praktiknya Anda tidak akan melihat hal-hal seperti ini.sumber
try...finally
blok tanpacatch
juga mencegah beberapa optimasi?Exception
objek adalah apa yang paling banyak memakan waktu.Mari kita ukur, ya?
Di komputer saya, ini mencetak sesuatu seperti:
Setidaknya dalam contoh sepele ini, pernyataan coba tidak memiliki dampak yang terukur pada kinerja. Jangan ragu untuk mengukur yang lebih kompleks.
Secara umum, saya sarankan untuk tidak khawatir tentang biaya kinerja konstruksi bahasa sampai Anda memiliki bukti masalah kinerja aktual dalam kode Anda. Atau seperti Donald Knuth menempatkan itu: "optimasi prematur adalah akar dari segala kejahatan".
sumber
-XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly
, baik loop dan tambahan di dalamnya hadir dalam kode asli yang dihasilkan. Dan tidak, metode abstrak tidak digarisbawahi, karena pemanggil mereka tidak hanya dalam waktu dikompilasi (mungkin, karena itu tidak dipanggil cukup kali).try
Sayacatch
mungkin memiliki dampak pada kinerja. Ini karena mencegah JVM dari melakukan beberapa optimasi. Joshua Bloch, dalam "Java Efektif," mengatakan yang berikut:sumber
Yap, seperti yang dikatakan orang lain, satu
try
blok menghambat beberapa optimisasi di seluruh{}
karakter yang mengelilinginya. Secara khusus, pengoptimal harus mengasumsikan bahwa pengecualian dapat terjadi pada titik mana pun dalam blok, sehingga tidak ada jaminan bahwa pernyataan dieksekusi.Sebagai contoh:
Tanpa itu
try
, nilai yang dihitung untukx
ditugaskan dapat disimpan sebagai "subekspresi umum" dan digunakan kembali untuk ditugaskany
. Tetapi karenatry
tidak ada jaminan bahwa ekspresi pertama pernah dievaluasi, maka ekspresi tersebut harus dihitung ulang. Ini biasanya bukan masalah besar dalam kode "garis lurus", tetapi bisa signifikan dalam satu lingkaran.Namun perlu dicatat bahwa ini HANYA berlaku untuk kode JITCed. javac hanya melakukan sejumlah optimasi piddling, dan tidak ada biaya untuk penerjemah bytecode untuk memasuki / meninggalkan
try
blok. (Tidak ada bytecode yang dihasilkan untuk menandai batas blok.)Dan untuk bestsss:
Keluaran:
output javap:
Tidak ada "GOTO".
sumber
catch/finally
bingkai.finally
dalam bytecode, itutry/catch(Throwable any){...; throw any;}
Dan Itu memang memiliki pernyataan menangkap w / a frame dan Throwable yang HARUS didefinisikan (bukan nol) dan sebagainya. Mengapa Anda mencoba berdebat tentang topik ini, Anda dapat memeriksa setidaknya beberapa bytecode? Pedoman untuk impl saat ini. dari akhirnya adalah menyalin blok dan menghindari bagian goto (imp sebelumnya) tetapi bytecodes harus disalin tergantung berapa banyak titik keluar yang ada.Untuk memahami mengapa optimasi tidak dapat dilakukan, penting untuk memahami mekanisme yang mendasarinya. Contoh paling ringkas yang dapat saya temukan diimplementasikan dalam makro C di: http://www.di.unipi.it/~nids/docs/longjump_try_trow_catch.html
Compiler sering mengalami kesulitan menentukan apakah lompatan dapat dilokalisasi ke X, Y dan Z sehingga mereka melewati optimisasi yang tidak dapat mereka yakini aman, tetapi implementasinya sendiri agak ringan.
sumber
Namun microbenchmark ( sumber ) lain.
Saya membuat tes di mana saya mengukur versi kode coba-tangkap dan tidak-coba-tangkap berdasarkan persentase pengecualian. Persentase 10% berarti bahwa 10% dari kasus uji dibagi dengan nol kasus. Dalam satu situasi itu ditangani oleh blok try-catch, yang lain oleh operator bersyarat. Ini tabel hasil saya:
Yang mengatakan bahwa tidak ada perbedaan yang signifikan antara semua kasus ini.
sumber
Saya menemukan penangkapan NullPointException cukup mahal. Untuk operasi 1.2k waktu adalah 200ms dan 12ms ketika saya mengatasinya dengan cara yang sama dengan
if(object==null)
yang merupakan peningkatan yang cukup bagi saya.sumber