Saya akan segera mengatakan: Saya tidak pernah menunggu jawaban rinci untuk pertanyaan ini pada jaminan sosial. Ini bodoh dan dalam kasus saya egois. Namun, menurut pendapat saya, selain minat umum pada platform, sangat berguna untuk mengetahui cara kerjanya, karena ini menghilangkan sejumlah masalah. Misalnya, itu mengecualikan opsi ketika pengembang percaya bahwa Dispose
dipanggil secara otomatis dan Anda tidak perlu menyebutnya sendiri. Atau jika pengembang lebih berpengalaman, membantunya secara otomatis, pada tingkat memori otot, tulis kode yang mengarah ke paling sedikit masalah.
Pertanyaan lain yang secara subyektif tidak saya sukai adalah bagaimana pekerjaannya dijelaskan. Oleh karena itu, saya mengusulkan pendekatan alternatif yang dijelaskan dalam buku saya, Arsitektur Platform NET .
Jika kita akan benar-benar memahami mengapa dua algoritma manajemen memori ini dipilih: Sweep dan Compact, kita harus mempertimbangkan lusinan algoritma manajemen memori yang ada di dunia: dimulai dengan kamus biasa dan berakhir dengan struktur bebas kunci yang sangat kompleks. Alih-alih, meninggalkan pikiran kita tentang apa yang berguna, kita hanya membenarkan pilihan dan dengan demikian memahami mengapa pilihan itu dibuat seperti itu. Kami tidak lagi melihat buklet peluncuran booster: kami memiliki satu set lengkap dokumentasi.
Perselisihan itu saling menguntungkan: jika tidak jelas, saya akan memperbaiki poin yang tidak jelas dalam buku ini , sebagian kecil di antaranya adalah teks yang diberikan.

Saya memilih format penalaran sehingga Anda merasa seperti arsitek platform dan saya sendiri sampai pada kesimpulan yang sama dengan arsitek asli datang ke kantor pusat Microsoft di Redmond.
Berdasarkan klasifikasi objek yang dialokasikan berdasarkan ukurannya, Anda dapat membagi ruang untuk alokasi memori menjadi dua bagian besar: tempat dengan objek berukuran di bawah ambang tertentu dan tempat dengan ukuran di atas ambang ini dan melihat perbedaan apa yang dapat dibuat dalam pengelolaan grup ini (berdasarkan pada ukuran mereka) dan apa yang terjadi.
Jika kita mempertimbangkan pengelolaan objek " kecil " secara konvensional, kita dapat melihat bahwa jika kita mematuhi gagasan menyimpan informasi tentang setiap objek, akan sangat mahal bagi kita untuk mempertahankan struktur data manajemen memori yang akan menyimpan tautan ke setiap objek tersebut. Pada akhirnya, mungkin ternyata untuk menyimpan informasi tentang satu objek, Anda akan membutuhkan memori sebanyak yang dibutuhkan oleh objek itu sendiri. Sebagai gantinya, Anda harus mempertimbangkan: jika selama pengumpulan sampah kita menari dari akar, masuk jauh ke grafik melalui bidang keluar dari objek, dan kita membutuhkan bagian linear sepanjang tumpukan hanya untuk mengidentifikasi objek sampah, apakah perlu bagi kita untuk menyimpan informasi tentang setiap objek dalam algoritma manajemen memori? Jawabannya jelas: tidak perlu untuk ini. Jadi, kita dapat mencoba untuk melanjutkan dari fakta bahwa kita tidak boleh menyimpan informasi seperti itu: kita dapat melalui banyak linier, mengetahui ukuran setiap objek dan memindahkan pointer setiap kali dengan ukuran objek berikutnya.
Tidak ada struktur data tambahan pada heap yang menahan pointer ke setiap objek yang heap kontrol.
Namun, ketika kita tidak lagi membutuhkan memori, kita harus membebaskannya. Dan ketika membebaskan memori, menjadi sulit bagi kita untuk mengandalkan lintasan linear tumpukan: itu panjang dan tidak efektif. Sebagai hasilnya, kita sampai pada kesimpulan bahwa kita perlu entah bagaimana menyimpan informasi tentang area memori bebas.
Tumpukan memiliki daftar memori bebas.
Jika, seperti yang kami putuskan, untuk menyimpan informasi tentang area bebas, dan sementara membebaskan memori, area ini terlalu kecil, maka pertama-tama kami akan mengalami masalah yang sama dalam menyimpan informasi tentang area bebas yang kami temui ketika mempertimbangkan area yang ditempati (jika di sisi satu objek yang ditempati dibebaskan, untuk menyimpan informasi tentang hal itu, perlu dalam kasus terburuk 2/3 dari ukurannya. Pointer + ukuran versus SyncBlockIndex + VMT + beberapa bidang - dalam kasus objek). Ini lagi-lagi terdengar boros, Anda harus mengakui: itu tidak selalu baik untuk membebaskan sekelompok objek yang saling mengikuti. Biasanya, mereka dilepaskan dalam kekacauan. Tetapi tidak seperti situs sibuk, yang tidak perlu kita cari secara linear, kita perlu mencari situs gratis karena ketika kita mengalokasikan memori, kita mungkin membutuhkannya lagi. Oleh karena itu, keinginan yang sepenuhnya alami muncul untuk mengurangi fragmentasi dan memeras tumpukan, memindahkan semua area yang ditempati ke tempat-tempat bebas, sehingga membentuk area luas area bebas di mana memori dapat dialokasikan.
Dari sinilah ide algoritma Compacting berasal.
Tapi tunggu, katamu. Bagaimanapun, operasi ini bisa sangat sulit. Bayangkan bahwa Anda membebaskan sebuah objek di awal tumpukan. Dan apa, katamu, apa kau perlu memindahkan semuanya ?? Yah, tentu saja, Anda bisa bermimpi tentang subjek instruksi vektor CPU, yang dapat Anda gunakan untuk menyalin area memori yang sangat besar. Tetapi ini hanyalah awal dari pekerjaan. Kita juga harus memperbaiki semua pointer dari bidang objek ke objek yang telah mengalami pergerakan. Operasi ini bisa memakan waktu sangat lama. Tidak, kita harus melanjutkan dari hal lain. Misalnya, dengan membagi seluruh segmen memori tumpukan ke dalam sektor dan bekerja dengannya secara terpisah. Jika kita bekerja secara terpisah di masing-masing sektor (untuk prediksi dan penskalaan prediksi ini - lebih disukai, ukuran tetap), gagasan kompresi tampaknya tidak terlalu berat: cukup untuk mengompres satu sektor dan kemudian Anda bahkan dapat mulai berbicara tentang waktu yang diperlukan untuk mengompres satu sektor tersebut .
Sekarang masih perlu memahami atas dasar apa untuk dibagi ke dalam sektor-sektor. Di sini kita harus beralih ke klasifikasi kedua, yang diperkenalkan pada platform: berbagi memori, berdasarkan waktu hidup elemen individualnya.
Pembagiannya sederhana: jika kita memperhitungkan bahwa kita akan mengalokasikan memori seiring bertambahnya alamat, maka objek yang dipilih pertama menjadi yang tertua, dan mereka yang berada di alamat senior menjadi yang termuda. Selanjutnya, karena pintar, Anda bisa sampai pada kesimpulan bahwa dalam aplikasi objek dibagi menjadi dua kelompok: mereka yang diciptakan untuk umur panjang dan mereka yang diciptakan untuk hidup sangat sedikit. Misalnya, untuk sementara menyimpan pointer ke objek lain dalam bentuk koleksi. Atau objek DTO yang sama. Dengan demikian, dari waktu ke waktu, memeras banyak kita mendapatkan sejumlah objek berumur panjang - di alamat bawah dan sejumlah berumur pendek - di senior.
Demikianlah kita telah menerima beberapa generasi .
Membagi memori menjadi beberapa generasi, kita mendapat kesempatan untuk lebih jarang melihat objek generasi yang lebih tua, yang semakin lama semakin banyak.
Tetapi pertanyaan lain muncul: jika kita hanya memiliki dua generasi, kita akan mendapatkan masalah. Atau kami akan mencoba untuk membuat GC bekerja dengan cepat tanpa topeng: maka ukuran generasi muda, kami akan mencoba untuk melakukan ukuran minimum. Akibatnya, objek secara tidak sengaja akan gagal pada generasi yang lebih tua (jika GC bekerja "sekarang, selama alokasi memori yang sangat besar untuk banyak objek"). Atau, untuk meminimalkan kegagalan yang tidak disengaja, kami akan meningkatkan ukuran generasi muda. Kemudian GC pada generasi muda akan bekerja cukup lama, memperlambat dan memperlambat aplikasi.
Jalan keluarnya adalah pengenalan generasi "menengah". Remaja Dengan kata lain, jika Anda hidup sampai remaja, Anda lebih cenderung hidup sampai usia tua. Inti dari pengenalannya adalah untuk mencapai keseimbangan antara mendapatkan generasi muda terkecil dan generasi tua yang paling stabil , di mana lebih baik untuk tidak menyentuh apa pun. Ini adalah zona di mana nasib benda belum diputuskan. Generasi pertama (jangan lupa apa yang kita pikirkan dari awal) juga dibuat kecil dan GC terlihat lebih jarang di sana. Dengan demikian, GC memungkinkan objek yang berada dalam generasi pertama sementara, tidak masuk ke generasi yang lebih tua, yang sangat sulit untuk dikumpulkan.
Jadi kami mendapat ide tiga generasi.
Lapisan optimasi berikutnya adalah upaya untuk menolak kompresi. Lagi pula, jika Anda tidak melakukannya, kami menyingkirkan lapisan besar pekerjaan. Mari kita kembali ke masalah situs gratis.
Jika setelah kita menggunakan semua memori yang tersedia di heap dan GC telah dipanggil, ada keinginan alami untuk menolak kompresi demi mengalokasikan memori lebih lanjut di dalam bagian yang dibebaskan jika ukurannya cukup untuk mengakomodasi sejumlah objek tertentu. Di sini kita sampai pada gagasan algoritma kedua untuk membebaskan memori dalam GC, yang disebut Sweep
: kita tidak memampatkan memori, kita menggunakan rongga dari objek yang dibebaskan untuk menempatkan objek baru
Jadi kami menggambarkan dan membenarkan semua dasar-dasar algoritma GC.
Jadi, setelah dua hari, kita bisa menarik beberapa kesimpulan. Seperti yang saya pahami, kebanyakan orang mengerti sebagian besar teks, atau bahkan keseluruhan. Beberapa orang menjawab bahwa mereka tidak mengerti, sebagian, masing-masing, sebagian mengerti. Perselisihan dimenangkan oleh tim pembaca, meskipun dengan sedikit margin, seperti yang mereka katakan. Tapi, seperti yang saya katakan, semua orang akan mendapat manfaat dari ini: teks akan diubah dan ditambah. Plus, diperbarui di kedua tempat: baik di buku dan di sini, di artikel.
