.net 4.0 中的特性總結(三):垃圾回收

1.內存基礎知識數組

  • 每一個進程都有其本身單獨的虛擬地址空間。 同一臺計算機上的全部進程共享相同的物理內存,若是有頁文件,則也共享頁文件。
  • 默認狀況下,32 位計算機上的每一個進程都具備 2 GB 的用戶模式虛擬地址空間。
  • 做爲一名應用程序開發人員,您只能使用虛擬地址空間,請勿直接操控物理內存。 垃圾回收器爲您分配和釋放託管堆上的虛擬內存。
  • 若是您編寫的是本機代碼,請使用 Win32 函數處理虛擬地址空間。 這些函數爲您分配和釋放本機堆上的虛擬內存。
  • 虛擬內存有三種狀態:

        可用。 該內存塊沒有引用關係,可用於分配。安全

        保留。 內存塊可供您使用,而且不能用於任何其餘分配請求。 可是,在該內存塊提交以前,您沒法將數據存儲到其中。服務器

         提交。 內存塊已指派給物理存儲。併發

  • 可能會存在虛擬地址空間碎片。 就是說地址空間中存在一些被稱爲孔的可用塊。 當請求虛擬內存分配時,虛擬內存管理器必須找到知足該分配請求的足夠大的單個可用塊。 即便您具備 2 GB 的可用空間,2 GB 的分配請求也有可能會不成功,除非全部這些空間必須位於單個的地址塊中。
  • 若是用完保留的虛擬地址空間或提交的物理空間,則可能會用盡內存。

2.垃圾回收的條件函數

當知足如下條件之一時將發生垃圾回收:測試

  • 系統具備低的物理內存。
  • 由託管堆上已分配的對象使用的內存超出了可接受的閾值。 這意味着可接受的內存使用的閾值已超過託管堆。 隨着進程的運行,此閾值會不斷地進行調整。
  • 調用 GC.Collect 方法。 幾乎在全部狀況下,您都沒必要調用此方法,由於垃圾回收器會持續運行。 此方法主要用於特殊狀況和測試

3.託管堆spa

在垃圾回收器由 CLR 初始化以後,它會分配一段內存用於存儲和管理對象。 此內存稱爲託管堆(與操做系統中的本機堆相對)。操作系統

每一個託管進程都有一個託管堆。 進程中的全部線程都在同一堆上分配對象。線程

當觸發垃圾回收時,垃圾回收器將回收由死對象佔用的內存。 回收進程會對活動對象進行壓縮,以便將它們一塊兒移動,並移除死空間,從而使堆更小一些。 這將確保一塊兒分配的對象全都位於託管堆上,從而保留它們的局部性。對象

垃圾回收的侵入性(頻率和持續時間)是由分配的數量和託管堆上保留的內存數量決定的。

此堆可視爲兩個堆的累計:大對象堆和小對象堆。

大對象堆包含其大小爲 85,000 個字節和更多字節的對象。大對象堆上的特大對象一般是數組 很是大的實例對象是不多見的。

4.代數

堆上的對象有三代:

  • 0 。 這是最年輕的代,其中包含短生存期對象。 短生存期對象的一個示例是臨時變量。 垃圾回收最常發生在此代中。
  • 新分配的對象構成新一代的對象而且爲隱式的第 0 代回收,除非它們是大對象,在這種狀況下,它們將進入第 2 代回收中的大對象堆。
  • 大多數對象經過第 0 代中的垃圾回收進行回收,不會保留到下一代。
  • 1 。 這一代包含短生存期對象並用做短生存期對象和長生存期對象之間的緩衝區。
  • 2 。 這一代包含長生存期對象。 長生存期對象的一個示例是服務器應用程序中的一個包含在進程期間處於活動狀態的靜態數據的對象。

當條件獲得知足時,垃圾回收將在特定代上發生。 回收某個代意味着回收此代中的對象及其全部更年輕的代。 第 2 代垃圾回收也稱爲完整垃圾回收,由於它回收全部代上的全部對象(即,託管堆中的全部對象)。

倖存和提高:垃圾回收中未回收的對象也稱爲倖存者,並會被提高到下一代。 在第 0 代垃圾回收中倖存的對象將被提高到第 1 代;在第 1 代垃圾回收中倖存的對象將被提高到第 2 代;而在第 2 代垃圾回收中倖存的對象將仍爲第 2 代。

當垃圾回收器檢測到某個代中的倖存率很高時,它會增長該代的分配閾值,所以下一次回收將會獲取一個很是大的回收內存。 CLR 會在如下兩個優先級別以前進行平衡:不容許應用程序的工做集獲取太大內存以及不容許垃圾回收花費太多時間。

5.垃圾回收過程當中發生的狀況

垃圾回收分爲如下幾個階段:

  • 標記階段,找到並建立全部活動對象的列表。
  • 重定位階段,用於更新對將要壓縮的對象的引用。
  • 壓縮階段,用於回收由死對象佔用的空間,並壓縮倖存的對象。 壓縮階段將垃圾回收中倖存下來的對象移至段中時間較早的一端。

由於第 2 代回收能夠佔用多個段,因此能夠將已提高到第 2 代中的對象移動到時間較早的段中。 能夠將第 1 代倖存者和第 2 代倖存者都移動到不一樣的段,由於它們已被提高到第 2 代。

將不會壓縮大對象堆,由於這會在一個不可接受的時間長度內增長內存使用量。

 

垃圾回收器使用如下信息來肯定對象是否爲活動對象:

  • 堆棧根。 由實時 (JIT) 編譯器和堆棧查看器提供的堆棧變量。
  • 垃圾回收句柄。 指向託管對象且可由用戶代碼或公共語言運行時分配的句柄。
  • 靜態數據。 應用程序域中可能引用其餘對象的靜態對象。 每一個應用程序域都會跟蹤其靜態對象。

在垃圾回收啓動以前,除了觸發垃圾回收的線程之外的全部託管線程均會掛起。

下圖演示了觸發垃圾回收並致使其餘線程掛起的線程。

image

6.後臺垃圾回收

在後臺垃圾回收中,在進行第 2 代回收的過程當中,將會根據須要收集暫時代(第 0 代和第 1 代)。 後臺垃圾回收沒法設置;它會自動運行並啓用併發垃圾回收。 後臺垃圾回收是對併發垃圾回收的替代。 與併發垃圾回收同樣,後臺垃圾回收是在一個專用線程上執行的而且只適用於第 2 代回收。

後臺垃圾回收期間對暫時代的回收稱爲前臺垃圾回收。 發生前臺垃圾回收時,全部託管線程都將被掛起。

當後臺垃圾回收正在進行而且您已在第 0 代中分配了足夠的對象時,CLR 將執行第 0 代或第 1 代前臺垃圾回收。 專用的後臺垃圾回收線程將在常見的安全點上進行檢查以肯定是否存在對前臺垃圾回收的請求。 若是存在,則後臺回收將掛起自身以便前臺垃圾回收能夠發生。 在前臺垃圾回收完成以後,專用的後臺垃圾回收線程和用戶線程將繼續。

後臺垃圾回收能夠消除併發垃圾回收所帶來的分配限制,由於在後臺垃圾回收期間,可發生暫時垃圾回收。 這意味着,後臺垃圾回收能夠移除暫時代中的死對象,並且還能夠在第 1 代垃圾回收期間根據須要展開堆。

後臺垃圾回收當前不可用於服務器垃圾回收

相關文章
相關標籤/搜索