2011-05-26 72 views
20

我有一個奇怪的情況,我想弄明白。觸發gen2垃圾回收的是什麼?

創世紀:

我運行我的程序在物理機上用核心和RAM 128GB。我試圖確定爲什麼它沒有使用所有可用的內核,通常它平均使用20-25%的CPU(因此16個內核中有4-5個內核)。當我查看性能計數器時,他們顯示的是60-70%的垃圾收集時間。

僅供參考,我使用.NET Framework 4和TPL(Parallel.ForEach)來編程我的程序的性能密集型部分。我將線程數量限制爲內核數量。

問題:

我創建了大量的對象,太多的垃圾收集器有效地處理,因此它在垃圾收集花費了大量的時間。

的簡單的解決方案到目前爲止:

我介紹對象池以減少對垃圾收集器中的壓力。我將繼續合併對象以提高性能,已經合併一些對象將垃圾收集時間從60-70%減少到45%,並且我的程序運行速度提高了40%。

揮之不去的問題(一個我希望你能爲我解答):在可用的RAM最14GB運行時使用,相比之下,RAM 128GB,這是相當小

我的程序。這臺機器上沒有別的東西在運行(它對我來說純粹是一個測試臺),並且有很多可用的RAM。

  • 如果有足夠的內存可用,爲什麼gen2(或全部)集合都會發生?相當大數量的這些gen2集合(成千上萬)正在發生。即如何確定啓動gen2集合的閾值?
  • 爲什麼垃圾收集器不會延遲任何完整收集,直到物理RAM上的壓力達到較高閾值爲止?
  • 有沒有什麼辦法可以配置垃圾收集器來等待更高的閾值? (即不打擾可言,如果沒有必要收集)

編輯:我已經使用的選項,使用服務器垃圾收集

...什麼我需要知道的是什麼觸發gen2集合,而不是服務器垃圾收集器更好(我已經知道了)。

回答

19

我記得,客戶端GC是默認的。我的經驗是在收集之前不會讓堆變得很大。對於我的重型加工應用程序,我使用「服務器」GC。

啓用在應用程序配置文件的服務器GC:

<?xml version ="1.0"?> 
<configuration> 
    <runtime> 
    <gcServer enabled="true"/> 
    </runtime> 
</configuration> 

這使得對我來說性能巨大差異。例如,我的一個程序花費了80%以上的時間進行垃圾回收。啓用服務器GC降低了10%多一點。內存使用增加了,因爲GC讓它去了,但對於我的大多數應用程序來說,這很好。

另一件會導致Gen 2收藏的事物是大對象堆。請參閱CLR Inside Out: Large Object Heap Uncovered。簡而言之,如果您超過了LOH閾值,它將觸發第2代收集。如果你分配了大量短暫的大型對象(大約85千字節),這將是一個問題。

+0

我已經在使用服務器垃圾收集器(由於每個核心規則有一個堆,所以它具有更多的核心性能)。雖然我感謝你的有用建議,但並沒有真正回答我的問題:( – 2011-05-27 01:06:12

+0

@傑弗裏:查看我的關於大對象堆的編輯。 – 2011-05-27 12:31:56

+0

這是一個很好的觀點。雖然我認爲我沒有這樣做,但是我的LOH堆通常只有一個陣列,但我會進一步深入檢查一下。 – 2011-05-27 13:10:06

5

從模糊的記憶和通讀:http://msdn.microsoft.com/en-us/library/ee787088.aspx,我認爲Gen 2 GC的一個觸發器可以是Gen 2段填充。該文章指出,服務器GC使用更大的段,因此如前所述,這對於您的性能可能很重要。

讓機器等待,直到它幾乎沒有內存空間,這意味着在某個階段你會得到一個地獄般的GC。這可能不理想。如果你在GC中的時間如此之長,這是一個跡象表明你分配了太多的物體,而這些物體已經存活了足夠長的時間,以便能夠通過第0代& 1,並以重複的方式進行。如果應用程序的內存使用量沒有隨着時間的推移而增加,這表明這些對象實際上是短暫的,但是活着的時間足夠長以保存0和1的集合。這是一個糟糕的情況 - 您正在分配一個短暫的物體,但支付完整的Gen 2收集成本來清理它。

如果是這樣的話,你有幾個不同的方向走:

  1. 儘量讓短暫的對象收藏越早(所以他們不使其向Gen 2和因此GC成本更低)
  2. 嘗試分配更少的短命對象(因此GC發生的頻率較低,並且在分配之前有更多時間使用短命令對象強制GC並將對象移至較老的一代)
  3. 使用堆棧分配值類型而不是短期對象的引用類型(如果它適合您的目的)
  4. 如果您知道需要大量這些對象,請將它們預先放在一起。聽起來好像你正在這樣做,但仍然有很多分配將GC保持在45%。如果您的游泳池不夠大,請先分配更多的空間 - 正如您所說的那樣,您有足夠的備用內存。

很可能所有這些的組合都是一個很好的解決方案。你需要很好地理解你分配什麼樣的對象,他們生活多久,以及他們實際需要活多久才能實現你的目標。

GC對生命期短的臨時性物體(如GC可快速收集)或具有長壽命的長期/永久性物體很滿意。在這兩個類別的中間分配大量對象就是你痛苦的地方。因此分配更少的或者改變他們的生命週期來匹配他們的使用場景。