確定正在執行的垃圾收集器
我在 Windows Server 2003 x64(2x Xeon 4 核心 procs)上執行一個大型 .net 4.0 x86 應用程序,並且遇到了我的應用程序每天約 2-3 次凍結 30 秒,然後恢復正常執行的問題。該應用程序每週僅重新啟動一次,並消耗 400-800 mb 的記憶體,所以我假設這些凍結是垃圾收集。我只在日誌中看到凍結,而不是實時,或者我會檢查任務管理器進行確認。
我試圖弄清楚哪個 .Net 4 GC 正在執行,如果沒有,如何將 GC 切換到新的並發後台 gc,或者如何確認這些實際上是 GC(Procmon 不顯示 .Net Win2k3 伺服器中的儀器)。
您在伺服器版本的 Windows 上執行,預設情況下您將獲得垃圾收集器的伺服器版本。它不進行後台收集,垃圾由多個執行緒收集,因此偶爾可觀察到的暫停並不罕見。您可以使用 app.exe.config 文件強制工作站版本:
<configuration> <runtime> <gcServer enabled="false"/> </runtime> </configuration>還要查看GC.RegisterForFullGCNotification()方法的文件,了解如何處理暫停的副作用。
.NET 4.5 版將支持伺服器 GC 的後台收集。
我已經在我的部落格上重新發布了這個答案:http: //dave-black.blogspot.com/2012/04/how-to-determine-which-garbage.html
您可以通過 2 種方法確定您正在執行的 GC 版本:
- 呼叫System.Runtime.GCSettings.IsServerGC屬性
- 使用 WinDbg 附加到程序並使用不帶引號的命令“!sos.threads”檢查您有多少個 GC 執行緒,並且(根據以下標準)…
你沒有說你有什麼樣的應用程序。如果您正在執行控制台應用程序、WinForm 應用程序或 Windows 服務,您將獲得 Workstation GC。僅僅因為您在伺服器作業系統上執行並不意味著您將獲得伺服器版本的 GC。如果您的應用程序未託管在多程序電腦上,則預設情況下您將獲得 Workstation GC - Concurrent。如果您的應用程序託管在多程序電腦上,則預設情況下您將獲得 ServerGC。
預設情況下,任何 IIS 或 CLR 自託管應用程序都將在 ServerGC 模式下執行。
以下適用於任何給定的 .NET 託管程序:
工作站氣相色譜儀
- 單機
- 總是掛起執行緒
- 1 個臨時 GC 堆 (SOH)、1 個 LOH GC 堆
- 在觸發 GC 的執行緒上執行
- 執行緒優先級與觸發GC的執行緒相同
工作站 GC - 並發
- 僅在 Gen2/LOH 中並發執行(完整集合)
- 與伺服器模式互斥
- 稍大的工作集
- 如果一段時間後不使用,GC 執行緒將過期
- 1 個臨時 GC 堆 (SOH)、1 個 LOH GC 堆
- 專用 GC 執行緒
- 執行緒優先級正常
伺服器垃圾回收
- 更大的段大小
- 比工作站 GC 更快
- 總是掛起執行緒
- 每個邏輯處理器(包括超執行緒)1 個臨時 GC 堆(SOH),每個邏輯處理器(包括超執行緒)1 個 LOH GC 堆
- 專用 GC 執行緒
- 執行緒優先級為 THREAD_PRIORITY_HIGHEST
無論 GC 模式如何,每個託管程序只有 1 個終結器執行緒。即使在並發 GC 期間,託管執行緒也會被掛起(阻塞)兩次以執行 GC 的某些階段。
一個鮮為人知的事實是,即使您嘗試設置 GC 的 Server 模式,您也可能不會在 Server GC 中執行;GC 最終確定哪種模式最適合您的應用程序,如果它確定您的 ServerGC 設置將對您的應用程序產生負面影響,它將覆蓋您的設置。此外,在單處理器電腦上執行的任何託管 CLR 應用程序都將覆蓋任何手動 GC 設置 - 在這種情況下,CLR 將始終使用工作站 GC 模式。
在 CLR 4.0 中,事情只有一點點變化
並發 GC 現在是後台 GC
Background GC 僅適用於 Workstation GC
舊(並發 GC):
- 在 Full GC 期間允許分配到臨時段大小結束
- 否則,暫停所有其他執行緒
新的(後台 GC):
- 如有必要,允許臨時 GC 與後台 GC 同時進行
- 性能要快得多
伺服器 GC 總是阻塞執行緒以收集任何代
在 CLR 4.5 中,事情只發生了一點點變化……再次
後台伺服器 GC:
- 伺服器 GC 不再阻塞。相反,它使用可以與使用者程式碼同時執行的專用後台 GC 執行緒 - 請參閱MSDN:Background Server GC
因此,在 .NET 4.5+ 中,所有應用程序現在都可以使用後台 GC *,*而不管它們使用哪種 GC。
.NET 4.7.1 GC 改進
.NET Framework 4.7.1 對垃圾收集 (GC) 進行了更改,以提高分配性能,尤其是對於大型對象堆 (LOH) 分配。這是由於架構更改將堆的分配鎖拆分為 2 個,用於小對象堆 (SOH) 和 LOH。進行大量 LOH 分配的應用程序應該會看到分配鎖爭用的減少,並看到更好的性能。這些改進允許在後台 GC (BGC) 掃描 SOH 時分配 LOH。通常 LOH 分配器會等待 BGC 掃描過程的整個持續時間,然後才能滿足分配記憶體的請求。這可能會阻礙性能。您可以在 PerfView 的 GCStats 中觀察到這個問題,其中有一個“LOH 分配暫停(由於後台 GC)> 200 毫秒事件”表。暫停原因是“等待 BGC 執行緒空閒列表”。