你能重現這個 64 位 .NET 4 GC 錯誤嗎?
**更新:**微軟現在已經重現了這個錯誤並正在努力修復。
在評估 .NET 平台在低延遲軟體開發方面的可行性時,我們發現了 .NET 4 並發工作站垃圾收集器中的一個嚴重錯誤,該錯誤可能導致應用程序一次掛起長達幾分鐘。
在我們的三台機器上,以下簡單的 C# 程序導致 GC 洩漏記憶體,直到沒有剩餘記憶體為止,並且啟動了一個龐大的 GC 循環,使程序停止了幾分鐘(!),同時回收了 11Gb 的堆:
static void Main(string[] args) { var q = new System.Collections.Generic.Queue<System.Object>(); while (true) { q.Enqueue(0); if (q.Count > 1000000) q.Dequeue(); } }您需要在具有 .NET 4 的 64 位 Windows 作業系統上針對 x64 進行編譯,並使用預設(互動式)延遲設置在預設(並發工作站)GC 下執行。
這是在這台機器上執行此程序時任務管理器的外觀:
請注意,當此程序需要不超過 100Mb 的記憶體時,此處會洩漏 11Gb 的堆。
我們現在已經積累了大約十幾個這個 bug 的 repros,用 F# 和 C# 編寫,當大部分 gen0 倖存時,它似乎與 GC 寫屏障中的一個 bug 有關。但是,微軟尚未能夠複製它。你可以嗎?如果是這樣,您能否盡可能準確地描述您的設置,以便我們可以嘗試準確縮小此錯誤出現所需的條件。
如果以 64 位執行,在 linqpad 中執行程式碼確實會導致巨大的記憶體消耗;以 32 位執行正常。
我有一個帶有 8GB 主記憶體的 Windows 7 x64 終極安裝(照常打更新檔);安裝了 VS.NET 和其他開發工具,因此可能會有一些奇怪的調試器鉤子,這些鉤子在其他空白機器上不存在。
奇怪的是他們還沒有複製它。你確定那裡沒有通訊故障嗎?
哦,使用“new object()”而不是裝箱的值類型會導致相同的問題(不足為奇),因此您可能希望從重現案例中刪除裝箱的混淆因素。
我無法重現它。我在具有 4 gigs ram 的 x64 上進行了嘗試,編譯為 ANY。最大記憶體使用量約為 2.5 gigs。最大 GC 暫停時間約為 1084 毫秒。
這是我的 GC ETW 統計資訊的輸出。
您還可以按時間獲取 GC 事件
您執行的類似跟踪輸出可能有助於了解幕後發生的事情。
在 .NET 4.0 中有提供框架跟踪資訊的 Windows 事件跟踪 (ETW)。這是GC特有的。
為了獲得這些資訊,有一個名為PerfView的工具
以下是使用該工具獲取 GC 資訊的步驟
- 以管理員身份啟動 cmd.exe,這需要收集 ETW 跟踪
- 啟動要跟踪的應用程序
- 發出命令“PerfMonitor.exe /process:4180 start”,其中 4180 是程序 ID
- 讓應用程序執行一段時間
- 然後發出“PerfMonitor.exe stop”
- 獲取報告“PerfMonitor.exe GCTime”的命令。這將生成一個報告並在瀏覽器中使用 GC 統計資訊打開它。


