Balikkan pertanyaan Anda. Pertanyaan yang benar-benar memotivasi adalah dalam keadaan apa kita dapat menghindari biaya pengumpulan sampah?
Nah, pertama, apa yang biaya pengumpulan sampah? Ada dua biaya utama. Pertama, Anda harus menentukan apa yang hidup ; yang membutuhkan banyak pekerjaan. Kedua, Anda harus memadatkan lubang yang terbentuk ketika Anda membebaskan sesuatu yang dialokasikan di antara dua hal yang masih hidup. Lubang-lubang itu boros. Tapi memadatkannya juga mahal.
Bagaimana kita bisa menghindari biaya ini?
Jelas jika Anda dapat menemukan pola penggunaan penyimpanan di mana Anda tidak pernah mengalokasikan sesuatu yang berumur panjang, kemudian mengalokasikan sesuatu yang berumur pendek, kemudian mengalokasikan sesuatu yang berumur panjang, Anda dapat menghilangkan biaya lubang. Jika Anda dapat menjamin bahwa untuk beberapa bagian penyimpanan Anda, setiap alokasi berikutnya lebih pendek dari yang sebelumnya dalam penyimpanan itu maka tidak akan pernah ada lubang dalam penyimpanan itu.
Tetapi jika kita telah memecahkan masalah lubang maka kita juga memecahkan masalah pengumpulan sampah . Apakah Anda memiliki sesuatu di penyimpanan yang masih hidup? Iya nih. Apakah semuanya dialokasikan sebelum berumur panjang? Ya - asumsi itu adalah bagaimana kita menghilangkan kemungkinan lubang. Karena itu yang perlu Anda lakukan adalah mengatakan "apakah alokasi terbaru masih hidup?" dan Anda tahu bahwa semuanya hidup di penyimpanan itu.
Apakah kita memiliki seperangkat alokasi penyimpanan di mana kita tahu bahwa setiap alokasi berikutnya lebih pendek dari alokasi sebelumnya? Iya nih! Kerangka aktivasi metode selalu dihancurkan dengan urutan yang berbeda karena mereka dibuat lebih singkat daripada aktivasi yang menciptakannya.
Oleh karena itu kami dapat menyimpan bingkai aktivasi di tumpukan dan mengetahui bahwa mereka tidak perlu dikumpulkan. Jika ada bingkai di tumpukan, seluruh rangkaian bingkai di bawahnya berumur panjang, sehingga tidak perlu dikumpulkan. Dan mereka akan dihancurkan dengan urutan yang berlawanan bahwa mereka diciptakan. Biaya pengumpulan sampah dengan demikian dihilangkan untuk bingkai aktivasi.
Itulah mengapa kami memiliki kumpulan sementara pada stack di tempat pertama: karena ini adalah cara mudah mengimplementasikan aktivasi metode tanpa menimbulkan penalti manajemen memori.
(Tentu saja biaya sampah mengumpulkan memori yang dirujuk oleh referensi pada bingkai aktivasi masih ada.)
Sekarang pertimbangkan sistem aliran kontrol di mana bingkai aktivasi tidak dihancurkan dalam urutan yang dapat diprediksi. Apa yang terjadi jika aktivasi yang berumur pendek dapat menimbulkan aktivasi yang berumur panjang? Seperti yang Anda bayangkan, di dunia ini Anda tidak lagi dapat menggunakan tumpukan untuk mengoptimalkan kebutuhan mengumpulkan aktivasi. Himpunan aktivasi dapat berisi lubang lagi.
C # 2.0 memiliki fitur ini dalam bentuk yield return
. Metode yang menghasilkan pengembalian akan diaktifkan kembali di lain waktu - waktu berikutnya yang disebut MoveNext - dan ketika itu terjadi tidak dapat diprediksi. Oleh karena itu informasi yang biasanya berada di tumpukan untuk bingkai aktivasi blok iterator malah disimpan di heap, di mana itu adalah sampah yang dikumpulkan ketika enumerator dikumpulkan.
Demikian pula, fitur "async / await" yang hadir dalam versi C # dan VB berikutnya akan memungkinkan Anda untuk membuat metode yang aktivasi "menghasilkan" dan "melanjutkan" pada titik yang ditentukan dengan baik selama aksi metode. Karena frame aktivasi tidak lagi dibuat dan dihancurkan dengan cara yang dapat diprediksi, semua informasi yang digunakan untuk disimpan dalam stack harus disimpan di heap.
Ini hanya kebetulan dalam sejarah yang kami putuskan selama beberapa dekade bahwa bahasa dengan bingkai aktivasi yang dibuat dan dihancurkan dengan cara yang benar-benar teratur sangat modis. Karena bahasa modern semakin kekurangan properti ini, berharap untuk melihat semakin banyak bahasa yang mengubah kelanjutan ke tumpukan sampah, bukan tumpukan.