Dalam hal kode di mana Anda harus melakukan pembersihan sumber daya sebelum keluar dari suatu fungsi, apakah ada perbedaan kinerja utama antara 2 cara melakukannya.
Membersihkan sumber daya sebelum setiap pernyataan pengembalian
void func() { login(); bool ret = dosomething(); if(ret == false) { logout(); return; } ret = dosomethingelse(); if(ret == false) { logout(); return; } dootherstuff(); logout(); }
Membersihkan sumber daya di blok akhirnya
void func() { login(); try { bool ret = dosomething(); if(ret == false) return; ret = dosomethingelse(); if(ret == false) return; dootherstuff(); } finally { logout(); } }
Saya melakukan beberapa tes dasar dalam program sampel dan sepertinya tidak ada banyak perbedaan. Saya jauh lebih suka finally
cara melakukan ini - tapi saya bertanya-tanya apakah itu akan menyebabkan kinerja apa pun dalam proyek besar.
java
performance
efficiency
pengguna93353
sumber
sumber
if(!cond)
, maka itu java yang membuat saya melakukan ini. Dalam C ++, begitulah cara saya menulis kode boolean dan juga untuk jenis lainnya - yaituint x;
if(!x)
. Karena java memungkinkan saya untuk menggunakan ini hanya untukbooleans
, saya benar-benar berhenti menggunakanif(cond)
&if(!cond)
di java.(someIntValue != 0)
daripada membandingkan daripada mengevaluasi boolean. Itu bau bagi saya, dan saya segera refactor ketika saya melihatnya di alam liar.Jawaban:
Seperti ditunjukkan dalam Seberapa lambat pengecualian Java? orang dapat melihat bahwa kelambatan
try {} catch {}
dalam instatiation pengecualian itu sendiri.Membuat pengecualian akan mengambil seluruh tumpukan panggilan dari runtime dan di sinilah biayanya. Jika Anda tidak menciptakan pengecualian, ini hanya sangat sedikit peningkatan dari waktu ke waktu.
Dalam contoh yang diberikan dalam pertanyaan ini tidak ada pengecualian, orang tidak akan mengharapkan ada pelambatan untuk membuatnya - mereka tidak dibuat. Alih-alih, yang ada di sini adalah
try {} finally {}
menangani deallokasi sumber daya di dalam blok akhirnya.Jadi untuk menjawab pertanyaan, tidak, tidak ada biaya runtime nyata dalam
try {} finally {}
struktur yang tidak menggunakan pengecualian (tidak pernah terdengar seperti yang terlihat). Apa yang mungkin mahal adalah waktu pemeliharaan ketika seseorang membaca kode dan melihat ini bukan gaya kode yang khas dan pembuat kode harus memikirkan bahwa sesuatu yang lain terjadi dalam metode ini setelahreturn
sebelum kembali ke panggilan sebelumnya.Seperti yang telah disebutkan, pemeliharaan adalah argumen untuk kedua cara melakukan ini. Sebagai catatan, setelah mempertimbangkan, preferensi saya akan menjadi pendekatan terakhir.
Pertimbangkan waktu pemeliharaan untuk mengajar seseorang struktur bahasa baru. Melihat
try {} finally {}
bukanlah sesuatu yang sering dilihat dalam kode Java dan karenanya dapat membingungkan orang. Ada tingkat waktu pemeliharaan untuk mempelajari struktur yang sedikit lebih maju di Jawa daripada yang biasa dilihat orang.The
finally {}
blok selalu berjalan. Dan inilah mengapa Anda harus menggunakannya. Pertimbangkan juga waktu pemeliharaan untuk debug pendekatan non-akhirnya ketika seseorang lupa untuk memasukkan logout pada waktu yang tepat, atau menyebutnya pada waktu yang tidak tepat, atau lupa untuk kembali / keluar setelah memanggilnya sehingga dipanggil dua kali. Ada begitu banyak kemungkinan bug dengan ini sehingga penggunaantry {} finally {}
tidak memungkinkan untuk dimiliki.Ketika menimbang kedua biaya ini, mahal dalam waktu perawatan untuk tidak menggunakan
try {} finally {}
pendekatan. Sementara orang dapat dicker tentang berapa banyak milidetik fraksional atau instruksi jvm tambahantry {} finally {}
blok dibandingkan dengan versi lain, orang juga harus mempertimbangkan jam yang dihabiskan dalam debugging cara kurang ideal untuk menangani deallokasi sumber daya.Tulis kode yang dapat dipelihara terlebih dahulu, dan lebih disukai dengan cara yang akan mencegah bug ditulis kemudian.
sumber
/programming/299068/how-slow-are-java-exceptions
Jawaban yang diterima pada pertanyaan ini menunjukkan membungkus panggilan fungsi dalam blok uji coba biaya kurang dari 5% dibandingkan panggilan fungsi telanjang. Sebenarnya melempar dan menangkap pengecualian menyebabkan runtime membengkak menjadi lebih dari 66x panggilan fungsi kosong. Jadi jika Anda mengharapkan desain pengecualian untuk melempar secara teratur maka saya akan mencoba menghindarinya (dalam kode kinerja kritis yang diprofilkan dengan benar), namun jika situasi luar biasa jarang maka itu bukan masalah besar.
sumber
Alih-alih mengoptimalkan - pikirkan apa yang dilakukan kode Anda.
Menambahkan blok akhirnya adalah implementasi yang berbeda - itu berarti bahwa Anda akan keluar pada setiap pengecualian.
Khususnya - jika login melempar pengecualian, perilaku di fungsi kedua Anda akan berbeda dari yang pertama.
Jika masuk dan keluar sebenarnya bukan bagian dari perilaku fungsi, maka saya menyarankan agar metode ini melakukan satu hal dan satu hal dengan baik:
dan harus berada dalam fungsi yang sudah dienkapsulasi dalam konteks yang mengelola login / logout karena ini tampaknya berbeda secara mendasar dari apa yang dilakukan kode utama Anda.
Posting Anda ditandai sebagai Java yang tidak terlalu saya kenal tetapi di .net saya akan menggunakan blok penggunaan untuk ini:
yaitu:
Dan konteks login memiliki metode Buang yang akan keluar dan membersihkan sumber daya.
Sunting: Saya sebenarnya tidak menjawab pertanyaan!
Saya tidak memiliki bukti yang terukur tetapi saya tidak berharap ini menjadi lebih mahal atau tentu saja tidak cukup mahal untuk itu layak untuk optimasi prematur.
Saya akan meninggalkan sisa jawaban saya karena walaupun tidak menjawab pertanyaan, saya pikir ini membantu untuk OP.
sumber
using
konstruksi .net Anda , dengan asumsi bahwa sumber daya yang dimaksud mengimplementasikanAutoCloseable
antarmuka.ret
variabel ini , yang hanya ditugaskan dua kali untuk diperiksa satu baris nanti. Buat ituif (dosomething() == false) return;
.ret2 = doSomethingElse(ret1)
, tetapi itu tidak relevan dengan pertanyaan sehingga dihapus.if (dosomething() == false) ...
adalah kode yang buruk. Gunakan yang lebih intutiveif (!dosomething()) ...
Asumsi: Anda sedang mengembangkan dalam kode C #.
Jawaban cepatnya adalah tidak ada performa yang signifikan dari penggunaan blok try / akhirnya. Ada hit kinerja ketika Anda melempar dan menangkap pengecualian.
Jawaban yang lebih panjang adalah melihat sendiri. Jika Anda melihat kode CIL yang mendasarinya dihasilkan ( misalnya reflektor gerbang merah maka Anda dapat melihat instruksi CIL yang mendasarinya dihasilkan dan melihat dampaknya seperti itu.
sumber
Seperti yang telah dicatat orang lain, kode ini akan memiliki hasil yang berbeda, jika salah satu
dosomethingelse
ataudootherstuff
melemparkan pengecualian.Dan ya, panggilan fungsi apa pun dapat menimbulkan pengecualian, setidaknya a
StackOVerflowError
! Meskipun jarang mungkin untuk menangani ini dengan benar (karena setiap fungsi pembersihan yang disebut mungkin akan memiliki masalah yang sama, dalam beberapa kasus (seperti menerapkan kunci misalnya) sangat penting untuk bahkan menangani dengan benar ...sumber