Dot-Net

如何在高並發程式碼中提高 .NET 4.0 的垃圾收集器性能?

  • April 9, 2011

我正在使用 .NET framework 4 中的任務並行庫(特別是Parallel.ForParallel.ForEach),但是在並行化一些看起來應該在雙核機器上輕鬆並行化的任務時,我的速度提升非常平庸。

在分析系統時,由於垃圾收集器,看起來有很多執行緒同步正在進行。我正在做很多對象分配,所以我想知道如何在最大限度地減少程式碼重寫的同時提高並發性。

例如,在這種情況下是否有一些有用的技術:

  • 我應該嘗試手動管理 GC 嗎?
  • 我應該使用Dispose嗎?
  • 我應該固定物體嗎?
  • 我應該做其他不安全的程式碼技巧嗎?

後記:

問題不在於 GC 執行太頻繁,而在於 GC 阻止了並發程式碼有效地並行執行。我也不認為“分配更少的對象”是一個可以接受的答案。這需要重寫太多的程式碼來解決並行化不佳的垃圾收集器。

我已經找到了一個有助於整體性能的技巧(使用 gcServer),但它對並發性能沒有幫助。換句話說Parallel.For,在令人尷尬的並行任務中,它只比串列 For 循環快 20%。

後記:

好的,讓我進一步解釋一下,我有一個相當大而復雜的程序:優化解釋器。它足夠快,但我希望它在給定並行任務(內置於我的語言中的原始操作)時的性能能夠很好地擴展,因為有更多的核心可用。我在評估期間分配了很多小對象。整個解釋器設計基於從單個多態基礎對象派生的所有值。這在單執行緒應用程序中效果很好,但是當我們嘗試將任務並行庫應用於並行評估時,沒有任何優勢。

在對為什麼任務並行庫沒有為這些任務正確地跨核心分配工作進行大量調查之後,罪魁禍首似乎是 GC。顯然,GC 似乎充當了瓶頸,因為它在幕後進行了一些我不明白的執行緒同步。

我需要知道的是:GC 到底在做什麼會導致大量並發程式碼在執行大量分配時表現不佳,以及除了分配更少的對象之外,我們如何解決這個問題。我已經想到了這種方法,並且需要大量重寫大量程式碼。

如果由於分配/GC-ed 過多的對象而導致 GC 執行過於頻繁,請嘗試分配更少的對象 :)

根據您的情況 - 嘗試重用現有對象,創建對像池,使用不會造成太大記憶體壓力的“較輕”對象(或更大以減少分配的對像數量)。

不要試圖通過顯式呼叫 GC.Collect 來“管理 GC”,它很少有回報(Rico Mariani 這麼說

http://blogs.msdn.com/ricom/archive/2003/12/02/40780.aspx

1)您不能也不應該手動管理 GC。

  1. Dispose 只是對 GC 的一個指示,只要他覺得合適,它就會通過。:P

避免這些問題的唯一方法是分析您的應用程序並儘可能避免分配新對象。當您找到垃圾收集器中的內容時,請嘗試一些池技術來重用這些數據並避免每次都重新創建它。

編輯:每當 GC 執行時,所有執行緒都必須進入睡眠狀態以允許它完成工作。如果收藏品與您的情況一樣多,這就是放緩的原因。除了減少新對象的生成之外,沒有其他可能的方法來管理它。

引用自:https://stackoverflow.com/questions/2311154