Manajemen Memori Otomatis

Manajemen memori otomatis adalah salah satu layanan yang disediakan Common Language Runtime selama Eksekusi Terkelola. Pengumpul sampah Common Language Runtime mengelola alokasi dan pelepasan memori untuk sebuah aplikasi. Untuk pengembang, ini berarti Anda tidak perlu menulis kode untuk melakukan tugas manajemen memori ketika Anda mengembangkan aplikasi terkelola. Manajemen memori otomatis dapat menghilangkan masalah umum, seperti lupa untuk membebaskan objek dan menyebabkan kebocoran memori, atau mencoba untuk mengakses memori untuk objek yang telah dibebaskan. Bagian ini menjelaskan bagaimana pengumpul sampah mengalokasikan dan melepaskan memori.

Mengalokasikan Memori

Saat Anda menginisialisasi proses baru, runtime menyimpan wilayah ruang alamat yang berdekatan untuk proses tersebut. Ruang alamat yang dicadangkan ini disebut timbunan terkelola. Timbunan terkelola mempertahankan penunjuk ke alamat tempat objek berikutnya yang ada di timbunan akan dialokasikan. Awalnya, penunjuk ini diatur ke alamat dasar timbunan terkelola. Semua jenis referensi dialokasikan pada tumpukan terkelola. Ketika aplikasi membuat jenis referensi pertama, memori dialokasikan untuk jenis di alamat dasar timbunan terkelola. Ketika aplikasi membuat objek berikutnya, pengumpul sampah mengalokasikan memori untuknya di ruang alamat segera setelah objek pertama. Selama ruang alamat tersedia, pengumpul sampah secara terus menerus mengalokasikan ruang untuk objek baru dengan cara ini.

Mengalokasikan memori dari tumpukan terkelola lebih cepat daripada alokasi memori yang tidak terkelola. Karena runtime mengalokasikan memori untuk suatu objek dengan menambahkan nilai ke penunjuk, itu hampir secepat mengalokasikan memori dari tumpukan. Selain itu, karena objek baru yang dialokasikan secara berurutan disimpan berdekatan dalam tumpukan terkelola, aplikasi dapat mengakses objek dengan sangat cepat.

Melepaskan Memori

Mesin pengoptimal pengumpul sampah menentukan waktu terbaik untuk menjalankan pengumpulan berdasarkan alokasi yang dibuat. Ketika pengumpul sampah melakukan pengumpulan, ia melepaskan memori untuk objek yang tidak lagi digunakan oleh aplikasi. Pengumpul sampah menentukan objek mana yang tidak lagi digunakan dengan memeriksa akar aplikasi. Setiap aplikasi memiliki satu set akar. Setiap akar merujuk pada objek di timbunan terkelola atau diatur ke null. Akar aplikasi termasuk bidang statis, variabel lokal dan parameter pada tumpukan utas, dan register CPU. Pengumpul sampah memiliki akses ke daftar akar aktif yang dikelola kompilator just-in-time (JIT) dan runtime. Dengan menggunakan daftar ini, ia memeriksa akar aplikasi, dan dalam prosesnya membuat grafik yang berisi semua objek yang dapat dijangkau dari akar.

Objek yang tidak ada dalam grafik tidak dapat dijangkau dari akar aplikasi. Pengumpul sampah menganggap benda-benda yang tidak terjangkau sampah dan akan melepaskan memori yang dialokasikan untuk mereka. Selama pengumpulan, pengumpul sampah memeriksa tumpukan yang dikelola, mencari blok ruang alamat yang ditempati oleh benda-benda yang tidak terjangkau. Setelah menemukan setiap objek yang tidak dapat dijangkau, pengumpul sampah akan menggunakan fungsi penyalinan memori untuk memadatkan objek yang dapat dijangkau dalam memori, sehingga akan membebaskan blok ruang alamat yang dialokasikan ke objek yang tidak dapat dijangkau. Setelah memori untuk objek yang dapat dijangkau telah dipadatkan, pengumpul sampah membuat koreksi penunjuk yang diperlukan sehingga akar aplikasi menunjuk ke objek di lokasi barunya. Ini juga memosisikan penunjuk tumpukan terkelola setelah objek terakhir yang dapat dijangkau. Perhatikan bahwa memori dipadatkan hanya jika koleksi menemukan sejumlah besar objek yang tidak dapat dijangkau. Jika semua objek dalam tumpukan yang dikelola bertahan dalam koleksi, maka tidak perlu pemadatan memori.

Untuk meningkatkan performa, runtime mengalokasikan memori untuk objek besar dalam timbunan terpisah. Pengumpul sampah secara otomatis melepaskan memori untuk benda-benda besar. Namun, untuk menghindari memindahkan benda-benda besar dalam memori, memori ini tidak dipadatkan.

Generasi dan Kinerja

Untuk mengoptimalkan kinerja pengumpul sampah, tumpukan yang dikelola dibagi menjadi tiga generasi: 0, 1, dan 2. Algoritma pengumpulan sampah runtime didasarkan pada beberapa generalisasi yang telah ditemukan oleh industri perangkat lunak komputer dengan bereksperimen dengan skema pengumpulan sampah. Pertama, lebih cepat untuk memadatkan memori untuk sebagian dari tumpukan yang dikelola daripada untuk seluruh tumpukan yang dikelola. Kedua, objek yang lebih baru akan memiliki masa hidup yang lebih pendek dan objek yang lebih tua akan memiliki masa pakai yang lebih lama. Terakhir, objek yang lebih baru cenderung terkait satu sama lain dan diakses oleh aplikasi sekitar waktu yang sama.

Pengumpul sampah runtime menyimpan objek baru di generasi 0. Objek yang dibuat di awal masa pakai aplikasi dan yang bertahan dari pengumpulan akan dipromosikan dan disimpan dalam generasi 1 dan 2. Proses promosi objek dijelaskan nanti dalam topik ini. Karena lebih cepat untuk memadatkan sebagian dari tumpukan yang dikelola daripada seluruh tumpukan, skema ini memungkinkan pengumpul sampah untuk melepaskan memori dalam generasi tertentu daripada melepaskan memori untuk seluruh tumpukan yang dikelola setiap kali melakukan pengumpulan.

Bahkan, pengumpul sampah melakukan pendataan saat generasi 0 sudah penuh. Jika aplikasi mencoba membuat objek baru ketika generasi 0 penuh, pengumpul sampah menemukan bahwa tidak ada ruang alamat yang tersisa di generasi 0 untuk dialokasikan untuk objek. Pengumpul sampah melakukan pengumpulan dalam upaya untuk membebaskan ruang alamat di generasi 0 untuk objek. Pengumpul sampah memulai dengan memeriksa objek-objek di generasi 0 alih-alih semua objek yang ada di timbunan terkelola. Ini adalah pendekatan yang paling efisien, karena objek baru cenderung memiliki masa pakai yang singkat, dan diharapkan banyak objek di generasi 0 tidak akan lagi digunakan oleh aplikasi ketika pengumpulan dilakukan. Selain itu, koleksi generasi 0 saja sering merebut kembali memori yang cukup untuk memungkinkan aplikasi untuk terus membuat objek baru.

Setelah pengumpul sampah melakukan kumpulan generasi 0, pengumpulan ini memampatkan memori untuk objek yang dapat dijangkau seperti yang dijelaskan dalam Merilis Memori sebelumnya dalam topik ini. Pengumpul sampah kemudian mempromosikan benda-benda ini dan mempertimbangkan bagian dari tumpukan yang dikelola generasi 1 ini. Karena objek yang bertahan dari pengumpulan cenderung memiliki masa hidup yang lebih lama, sangat wajar untuk mempromosikannya ke generasi yang lebih tinggi. Akibatnya, pengumpul sampah tidak perlu memeriksa kembali benda-benda di generasi 1 dan 2 setiap kali melakukan pengumpulan generasi 0.

Setelah pengumpul sampah melakukan pengumpulan pertama generasi 0 dan mempromosikan objek yang dapat dijangkau ke generasi 1, ia mempertimbangkan sisa tumpukan yang dikelola generasi 0. Ini terus mengalokasikan memori untuk objek baru di generasi 0 sampai generasi 0 penuh dan perlu untuk melakukan koleksi lain. Pada titik ini, mesin pengoptimal pengumpul sampah menentukan apakah perlu untuk memeriksa benda-benda pada generasi yang lebih tua. Misalnya, jika koleksi generasi 0 tidak merebut kembali memori yang cukup untuk aplikasi untuk berhasil menyelesaikan upayanya untuk membuat objek baru, pengumpul sampah dapat melakukan pengumpulan generasi 1, kemudian generasi 2. Jika ini tidak merebut kembali memori yang cukup, pengumpul sampah dapat melakukan pengumpulan generasi 2, 1, dan 0. Setelah setiap koleksi, pengumpul sampah memadatkan benda-benda yang dapat dijangkau di generasi 0 dan mempromosikannya ke generasi 1. Objek di generasi 1 yang bertahan dari pengumpulan akan dipromosikan ke generasi 2. Karena pengumpul sampah hanya mendukung tiga generasi, benda-benda di generasi 2 yang bertahan koleksi tetap berada di generasi 2 sampai mereka bertekad untuk tidak terjangkau dalam koleksi masa depan.

Merilis Memori untuk Sumber Daya yang Tidak Dikelola

Untuk sebagian besar objek yang dibuat aplikasi Anda, Anda dapat mengandalkan pengumpul sampah untuk secara otomatis melakukan tugas manajemen memori yang diperlukan. Namun, sumber daya yang tidak dikelola memerlukan pembersihan eksplisit. Jenis sumber daya yang tidak dikelola paling umum adalah objek yang membungkus sumber daya sistem operasi, seperti penanganan file, penanganan jendela, atau koneksi jaringan. Meskipun pengumpul sampah dapat melacak masa pakai objek terkelola yang merangkum sumber daya yang tidak dikelola, ia tidak memiliki pengetahuan khusus tentang cara membersihkan sumber daya. Saat Anda membuat objek yang merangkum sumber daya yang tidak dikelola, disarankan agar Anda memberikan kode yang diperlukan untuk membersihkan sumber daya yang tidak dikelola dalam metode Pembuangan publik. Dengan menyediakan metode Pembuangan, Anda memungkinkan pengguna objek Anda untuk secara eksplisit membebaskan memorinya ketika mereka selesai dengan objek. Saat Anda menggunakan objek yang merangkum sumber daya yang tidak dikelola, Anda harus mengetahui Pembuangan dan menyebutnya seperlunya. Untuk informasi selengkapnya tentang membersihkan sumber daya yang tidak dikelola dan contoh pola desain untuk menerapkan Pembuangan, lihat Pengumpulan Sampah.

Lihat juga