由 .NET 程序分配的記憶體何時釋放回 Windows
設置
.NET 為每一代的堆(0、1、2、LOH)分段分配記憶體,以在啟動時以及在收集後嘗試滿足分配請求時獲得連續的記憶體塊。
為每個堆分配的記憶體可能會隨著應用程序“熱身”而趨於平穩,但可能用於第 2 代和大型對象堆。在垃圾回收期間,每個堆 (0, 1, 2) 都會被清掃和壓縮,但大對象堆 (LOH) 除外,它只是被清掃。
我理解集合的“掃描”部分意味著 GC 辨識哪些對像不再是根並且可用於收集(或終結),並且“緊湊”意味著在堆中仍然存在的地址被重新組織,所以可用的剩餘堆有更多可用的連續記憶體。
當超出堆內每個段的預算時,.NET 將分配另一個段以盡可能滿足分配。
問題
我的問題歸結為每個堆中的記憶體會發生什麼,應用程序(已送出)不再使用,但仍由.NET保留? 它何時發布回作業系統?.
我相信這是一個程序可能會消耗大量記憶體的場景(虛擬大小很大,但私有字節很小),但是在檢查它的堆時主要是空閒空間。作為另一個警告,堆的總大小也可能非常小,並且不考慮程序消耗的記憶體。
沒有阻塞的終結器,並且所有程序看起來都很健康——它可能在觸發監視器警報之前已經執行了數週(例如)。
為了進一步澄清這個問題,如果您閱讀 Tess .NET Memory Management - A Restaurant Analogy,如果表是堆段,餐廳是否會失去表(例如空閒堆段)?
編輯
- 刪除了對工作集和雞的混淆參考
- 添加了對 Tess 餐廳類比的參考
我的回答是——沒關係。作業系統為應用程序(.NET 執行時在其中執行)提供虛擬記憶體。這不是“真實”的記憶。作業系統可以將虛擬記憶體的每一頁放在牠喜歡的任何地方——處理器上、主記憶體中、磁碟上。因此,應用程序使用的記憶體可能超過系統上的 RAM 量,並且作業系統會將所需的位複製到磁碟或從磁碟複製以確保應用程序繼續執行(以某些定址和技術限制為模)。
作業系統管理系統上所有程序的虛擬記憶體,並確保一個程序不會佔用系統上的所有 RAM 以損害其他程序。當 .NET 執行時向系統請求在堆中使用的記憶體,但隨後沒有使用它時,該記憶體將(如果系統的可用 RAM 不足)被移動到磁碟,因為它沒有被訪問.
*苔絲通過電子郵件澄清:(*強調我的)
段大小在整個應用程序過程中保持不變,但這裡有兩件事需要考慮。
- 段的分配是虛擬分配,這意味著雖然我們保留虛擬記憶體,但我們只送出我們實際使用的內容,因此用於段的私有字節與段大小不同,這意味著在 GC 之後,您的私有字節將下降,而您的虛擬字節將保持不變。
- 當不再使用段時,即如果您碰巧對段中的所有內容進行 GC,使其不再包含任何 .net 對象,則將虛擬分配返回給作業系統。
相信這一點,然後堆段(餐廳表)將返回給作業系統。