Praktik terbaik untuk memfasilitasi pengumpulan sampah di .Net

Di Microsoft.Net, pengumpulan sampah adalah mekanisme yang diadopsi oleh Common Language Runtime (CLR) untuk membersihkan sumber daya yang dikonsumsi oleh aplikasi Anda. Saat Anda membuat objek di .Net, objek tersebut disimpan di heap terkelola. Meskipun Anda perlu membuat objek, dalam banyak kasus, Anda tidak perlu khawatir tentang membersihkan objek - runtime akan melakukannya untuk Anda.

Namun, Anda harus mengadopsi praktik terbaik dalam aplikasi Anda untuk memfasilitasi pengumpulan sampah dan membantunya membersihkan sumber daya lebih cepat. Meskipun .Net mahir mengklaim kembali objek yang dikelola, Anda harus mengikuti pedoman tertentu untuk memfasilitasi pengumpulan sampah yang lebih cepat guna meningkatkan kinerja aplikasi Anda. Pada artikel ini saya ingin menyajikan diskusi tentang cara kerja pengumpulan sampah dan praktik terbaik yang terlibat untuk memfasilitasi pengumpulan sampah di .Net.

Kapan pengumpulan sampah dilakukan?

Pengumpulan sampah terjadi saat sistem kehabisan memori fisik yang tersedia atau GC.Collect()metode tersebut dipanggil secara eksplisit dalam kode aplikasi Anda. Objek yang tidak lagi digunakan atau tidak dapat dijangkau dari root adalah kandidat untuk pengumpulan sampah. Intinya, pengumpul sampah membersihkan memori yang ditempati oleh objek yang tidak memiliki referensi.

Generasi

Waktu proses mengatur heap terkelola menjadi beberapa generasi. Ia menggunakan generasi ini untuk mengatur objek berumur pendek dan panjang. Perlu dicatat bahwa pengumpul sampah bekerja lebih sering pada generasi yang lebih rendah daripada generasi yang lebih tinggi. Generasi 0 berisi objek berumur pendek seperti objek sementara. Ketika sebuah objek dibuat, itu disimpan di Generasi 0 kecuali jika itu adalah objek yang besar. Jika objek adalah objek besar, itu disimpan di Large Object Heap (LOH) di Generasi 2. Dalam kebanyakan kasus, objek Generasi 0 diambil kembali oleh pengumpul sampah saat berjalan di latar belakang.

Saat menulis kode, Anda harus mematuhi praktik terbaik tertentu. Sebagai contoh, Anda harus membuat objek dalam lingkup lokal sebanyak mungkin untuk memfasilitasi pengumpulan sampah. Objek yang dibuat dalam cakupan yang lebih tinggi umumnya berada di memori untuk jangka waktu yang lebih lama. Anda dapat memanfaatkan profiler CLR untuk memahami pola alokasi aplikasi Anda.

Anda harus menghindari pemanggilan GC.Collect()metode karena menyebabkan pengumpulan penuh dari semua generasi (Generasi 0, 1, dan 2). Saat Anda melakukan panggilan ke GC.Collect()metode, waktu proses mengunjungi semua objek langsung di aplikasi Anda. Ini membutuhkan banyak waktu dan, karenanya, merupakan operasi yang sangat mahal. Akibatnya, memanggil GC.Collect()metode ini bukanlah praktik yang baik .

Jika Anda harus memanggil GC.Collect()metode tersebut, Anda harus memanggilnya GC.WaitForPendingFinalizers()setelah panggilan GC.Collect()untuk memastikan bahwa thread yang sedang menjalankan saat ini menunggu hingga finalizer untuk semua objek telah dijalankan.

Selanjutnya, Anda harus melakukan panggilan ke GC.Collect()metode lagi untuk memastikan bahwa Anda mengumpulkan benda mati yang tersisa. Objek mati ini yang mungkin telah dibuat karena panggilan ke metode finalizer pada objek. Cuplikan kode berikut menunjukkan bagaimana metode ini digunakan.

System.GC.Collect();

System.GC.WaitForPendingFinalizers();

System.GC.Collect();

Anda harus memastikan bahwa Anda meminimalkan alokasi tersembunyi dan menulis kode Anda sedemikian rupa sehingga peluang promosi objek berumur pendek ke generasi yang lebih tinggi dihilangkan. Anda tidak boleh mereferensikan objek berumur pendek dari yang berumur panjang untuk menghindari promosi objek berumur pendek ke generasi yang lebih tinggi.

Anda juga harus menghindari menulis finalis untuk kelas Anda. Jika Anda memiliki finalizer yang diimplementasikan di kelas Anda, objek dari kelas tersebut akan menjadi objek berumur panjang karena waktu proses perlu mempromosikan objek yang dapat diselesaikan ke generasi yang lebih lama. Anda harus menyetel objek ke null sebelum membuat panggilan yang berjalan lama jika objek tersebut tidak diperlukan oleh aplikasi. Jika Anda tidak lagi membutuhkan objek statis atau objek lain dalam aplikasi Anda, Anda harus menyetelnya ke null sebelum membuat panggilan yang berjalan lama. Anda tidak boleh menyetel variabel lokal ke null karena tidak diperlukan; runtime dapat menentukan objek lokal mana yang tidak direferensikan dalam kode Anda atau tidak digunakan lebih lanjut, jadi Anda tidak perlu menyetel variabel lokal apa pun ke null secara eksplisit.