eryksun telah menjawab pertanyaan # 1, dan saya telah menjawab pertanyaan # 3 (yang asli # 4), tetapi sekarang mari kita jawab pertanyaan # 2:
Mengapa ia merilis 50,5mb khususnya - berapakah jumlah yang dilepaskan berdasarkan?
Apa yang menjadi malloc
dasarnya adalah, pada akhirnya, seluruh rangkaian kebetulan di dalam Python dan itu sangat sulit diprediksi.
Pertama, tergantung pada bagaimana Anda mengukur memori, Anda mungkin hanya mengukur halaman yang sebenarnya dipetakan ke dalam memori. Dalam hal ini, setiap kali halaman ditukar oleh pager, memori akan muncul sebagai "dibebaskan", meskipun belum dibebaskan.
Atau Anda mungkin mengukur halaman yang sedang digunakan, yang mungkin atau mungkin tidak menghitung halaman yang dialokasikan tetapi tidak pernah disentuh (pada sistem yang optimis alokasi berlebihan, seperti linux), halaman yang dialokasikan tetapi ditandai MADV_FREE
, dll.
Jika Anda benar-benar mengukur halaman yang dialokasikan (yang sebenarnya bukan hal yang sangat berguna untuk dilakukan, tetapi tampaknya itu yang Anda tanyakan), dan halaman benar-benar telah dialokasikan, dua keadaan di mana hal ini dapat terjadi: Entah Anda telah digunakan brk
atau setara untuk mengecilkan segmen data (sangat jarang saat ini), atau Anda telah menggunakan munmap
atau mirip untuk melepaskan segmen yang dipetakan. (Secara teoritis juga ada varian kecil untuk yang terakhir, dalam hal itu ada cara untuk melepaskan bagian dari segmen yang dipetakan — misalnya, mencurinya dengan MAP_FIXED
untuk MADV_FREE
segmen yang Anda segera hapus peta.)
Tetapi sebagian besar program tidak secara langsung mengalokasikan hal-hal dari halaman memori; mereka menggunakan malloc
pengalokasi-gaya. Saat Anda menelepon free
, pengalokasi hanya dapat merilis halaman ke OS jika Anda kebetulan menjadi free
objek langsung terakhir dalam pemetaan (atau di halaman N terakhir dari segmen data). Tidak mungkin aplikasi Anda dapat memprediksi hal ini secara wajar, atau bahkan mendeteksi bahwa itu terjadi sebelumnya.
CPython membuat ini lebih rumit - ia memiliki pengalokasi objek 2-tingkat kustom di atas pengalokasi memori kustom di atas malloc
. (Lihat komentar sumber untuk penjelasan yang lebih terperinci.) Dan di atas itu, bahkan pada level C API, apalagi Python, Anda bahkan tidak secara langsung mengontrol ketika objek level atas dideallocated.
Jadi, ketika Anda merilis objek, bagaimana Anda tahu apakah itu akan melepaskan memori ke OS? Yah, pertama-tama Anda harus tahu bahwa Anda telah merilis referensi terakhir (termasuk referensi internal apa pun yang Anda tidak tahu), memungkinkan GC untuk membatalkan alokasi itu. (Tidak seperti implementasi lainnya, setidaknya CPython akan membatalkan alokasi objek segera setelah diizinkan.) Ini biasanya membatalkan alokasi setidaknya dua hal di tingkat berikutnya ke bawah (misalnya, untuk string, Anda melepaskan PyString
objek, dan buffer string ).
Jika Anda melakukan deallocate objek, untuk mengetahui apakah ini menyebabkan tingkat berikutnya turun untuk mendelallocasi blok penyimpanan objek, Anda harus mengetahui keadaan internal pengalokasi objek, serta bagaimana itu diterapkan. (Ini jelas tidak dapat terjadi kecuali Anda membatalkan alokasi hal terakhir di blok, dan bahkan kemudian, itu mungkin tidak terjadi.)
Jika Anda melakukan deallocate blok penyimpanan objek, untuk mengetahui apakah ini menyebabkan free
panggilan, Anda harus mengetahui keadaan internal pengalokasi PyMem, serta bagaimana itu diterapkan. (Sekali lagi, Anda harus deallocating blok yang terakhir digunakan dalam malloc
wilayah ed, dan bahkan kemudian, itu mungkin tidak terjadi.)
Jika Anda melakukan free
suatu malloc
wilayah ed, untuk mengetahui apakah ini menyebabkan munmap
atau setara (atau brk
), Anda harus tahu keadaan internal malloc
, serta bagaimana hal itu dilaksanakan. Dan yang ini, tidak seperti yang lain, sangat spesifik platform. (Dan sekali lagi, Anda umumnya harus membatalkan alokasi yang terakhir digunakan malloc
dalam suatu mmap
segmen, dan bahkan kemudian, itu mungkin tidak terjadi.)
Jadi, jika Anda ingin memahami mengapa itu terjadi untuk melepaskan tepat 50,5mb, Anda harus melacaknya dari bawah ke atas. Mengapa tidak malloc
memetakan nilai halaman 50,5mb saat Anda melakukan satu free
panggilan atau lebih (untuk mungkin sedikit lebih dari 50,5mb)? Anda harus membaca platform Anda malloc
, dan kemudian berjalan di berbagai tabel dan daftar untuk melihat kondisi saat ini. (Pada beberapa platform, bahkan mungkin menggunakan informasi tingkat sistem, yang hampir tidak mungkin ditangkap tanpa membuat snapshot dari sistem untuk memeriksa offline, tetapi untungnya ini biasanya bukan masalah.) Dan kemudian Anda harus lakukan hal yang sama pada 3 level di atas itu.
Jadi, satu-satunya jawaban yang berguna untuk pertanyaan itu adalah "Karena."
Kecuali jika Anda melakukan pengembangan terbatas sumber daya (misalnya tertanam), Anda tidak punya alasan untuk peduli tentang detail ini.
Dan jika Anda sedang melakukan pengembangan sumber daya terbatas, mengetahui rincian ini tidak berguna; Anda cukup banyak harus melakukan end-run di sekitar semua level tersebut dan khususnya mmap
memori yang Anda butuhkan di level aplikasi (mungkin dengan satu pengalokasi zona aplikasi khusus yang sederhana, dipahami dengan baik di antaranya).