垃圾回收(GC)是托管語言必備的技術之一,GC 的性能是影響托管語言性能的關鍵,我們的 .NET 既能寫桌面程式 (WINFROM , WPF) 又能寫 web 程式 (ASP.NET CORE),甚至還能寫移動端程式,,,不同使用場景的程式對 GC 的風格也有不同的要求,比如桌面程式更注重界面的回應速度,web 程式注重的是吞吐量,有幸的是 CLR 為我們提供了2種不同的 GC 模式與風格,
Workstation GC
作業站模式被設計為客戶端(桌面)程式使用,或者某些只有1個核心的機器使用,作業站模式下 GC 的回收頻次會加快,但是每一次 GC 造成的停頓很短暫,作業站模式的垃圾回收直接發生在觸發垃圾回收的用戶執行緒上,所以垃圾回收執行緒需要跟其他用戶執行緒去競爭 CPU 時間,作業站模式下只會分配一個 GC 堆,在作業站模式下 GC 分配的記憶體會更少,
Server GC
服務器模式適合大型的服務端應用,比如 ASP.NET Core 程式,服務器模式下 GC 的回識訓盡量的延遲,從而減少停頓,為了獲得更高的吞吐量與性能,程式會分配更多的記憶體,服務器模式下 CLR 根據 CPU 核心數量來分配 GC 堆的數量,同時為每個 GC 堆分配一個專用執行緒來執行回收,并且這個執行緒的優先級為 THREAD_PRIORITY_HIGHEST ,所以在與普通執行緒競爭的時候更容易獲得 CPU 時間,服務器模式通常具有更大容量的記憶體分段,分段容量的大小不是固定的,它跟 OS,邏輯 CPU 數量有關系:

設定使用 workstation 或者 server 模式
根據微軟的檔案上寫的客戶端單機程式默認的GC模式是 workstation ,ASP.NET 的 GC 模式取決于主機,如果不清楚默認的 GC 作業模式可以直接指定模式,
在不同的 .NET 版本下有不同的設定方式,參見下圖:

我們上面說的 workstation 模式跟 server 模式是 GC 的兩個主要模式,而 GC 在這兩個模式之下還有兩個不同的子風格 Non-Concurrent 跟 Background (concurrent) 風格,
Non-Concurrent
根據 CLR 之前的設計,如果 GC 執行緒啟動那么所有其他的執行緒都會掛起,

回收 0代、1代這種短代(ephemeral generations)速度是非常快,但是回收2代垃圾物件就相對比較慢,如果執行緒一直掛起會對程式的回應造成比較大的影響,于是 CLR 設計了 background(concurrent) GC , background GC 使用專用執行緒來回收2代物件,并且回收的時候不會掛起其他執行緒,
Background
在 background(concurrent) GC 回收執行的時候,0,1代的回收可以同步進行,background(concurrent) GC 使用一個或者多個專用執行緒來執行回收動作,
在 .NET Framework 4 之前稱之為 concurrent GC ,之后稱之為 background GC ,在 .NET Framework 4 時代,background GC 只支持在 workstation GC 模式下開啟,從 .NET Framework 4.5 開始 background GC 同時支持 workstation , server 模式,以下不再區分 background 跟 concurrent GC,統一使用 background 來描述,
background GC 運行的時候并不會掛起其他執行緒,但是反過來如果 1,2 代的 GC 正在運行那么會掛起其他所有的執行緒,包括 background 專用執行緒,
background GC 在 workstation 跟 server 模式下有一些區別:
in workstation mode
在 workstation 模式下 background GC 使用一個專用執行緒,

通過上圖我們可以看到:THREAD 1 發生 GC 的時候 其他執行緒包括 background GC 執行緒都會暫停,而 GC THREAD (background)啟動的時候則不會掛起其他執行緒,而且 GC THREAD 執行緒只有一個 ,
in server mode
在 server 模式下 background GC 會使用多個專用執行緒,執行緒的數量取決于邏輯處理器的數量,與在 workstation 模式下不同,server 模式下的 background GC 執行緒不會超時,

上圖中 GC THREAD1、2 代表 FGC 執行緒,它執行的時候會掛起其他所有的執行緒包括 BGC 執行緒,圖中的 BGC THREAD1、2 代表專用 background GC 執行緒,可以看到它執行的時候不會掛起其他執行緒,而且執行緒的數量并不是唯一的,
開啟關閉 background GC
根據微軟的檔案說明,在 Server 模式下,background 是默認的 GC 風格,也可以直接通過配置開啟 background GC ,
在不同的 .NET 版本下有不同的配置方式,參見下圖:

總結
通過以上我們對 GC 的 workstation / server 模式,以及 no-concurrent 跟 background GC 風格有了一定的了解,總結一下:如果你的程式是個客戶端程式需要 UI 更快的回應,希望 GC 造成的用戶執行緒暫停時間更短那么選用 workstation 模式,如果你的電腦只有一個處理器那么也選擇 workstation 模式,如果你的程式是大型 web 服務,你希望盡可能的利用服務器 CPU 與記憶體從而獲得更大的吞吐量與性能,那么選用 server 模式,在 server 模式下我們也應該盡量使用 background GC ,因為它可以更加充分的利用的多核處理器的優勢來進行 GC 操作,
參考
workstation-server-gc
wbackground-gc
fundamentals-gc
CLR 的 GC 作業模式介紹
understanding-different-gc-modes-with-concurrency-visualizer
關注我的公眾號一起玩轉技術

QQ群:1022985150 VX:kklldog 一起探討學習.NET技術
作者:Agile.Zhou(kklldog)
出處:http://www.cnblogs.com/kklldog/
本文著作權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利,
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/472221.html
標籤:.NET Core
上一篇:.NET 中 GC 的模式與風格
