2010-05-26 102 views
4

繼續從Understanding VS2010 C# parallel profiling results,但更重要的是討論:每線程內存管理在C#

我有很多,在並行工作線程(使用的Parallel.For /每次),它使用許多內存分配小班。

這會在全局內存分配器線程上產生爭用。

有沒有辦法指示.NET爲每個線程預分配一個內存池,並從該池中進行所有分配?

目前我的解決辦法是我自己的實現內存池(T型,這是在線程之間循環的對象的全局分配陣列),幫助了很多,但效率不高,因爲:

  1. 我可以」 t指示.NET從特定的內存片分配。
  2. 我仍然需要多次撥打新的來分配池的內存。

謝謝,

+0

是否有可能使T成爲值類型並將其分配到堆棧而不是堆中? – 2010-05-26 13:58:03

+1

這裏有什麼問題。你的程序運行緩慢嗎?內存不足,即。崩潰?只是使用大量的內存? – 2010-05-26 14:02:09

+0

@tehMich:我不這麼認爲。這些對象是複合類,將它們分解爲單獨的變量或數組將會很麻煩。此外,他們需要大量,我不知道會適合堆棧(我說的是數十兆字節)。 – Haggai 2010-05-26 15:03:39

回答

15

我搜索了兩天,試圖找到你遇到的同一問題的答案。答案是你需要將垃圾收集模式設置爲服務器模式。默認情況下,垃圾收集模式設置爲工作站模式。 將垃圾收集設置爲服務器模式會導致託管堆分裂爲單獨管理的部分,每個CPU一個部分。 要做到這一點,你需要添加一個配置設置到你的app.config文件。

<runtime> 
    <gcServer enabled="true"/> 
</runtime> 

我的12核Opteron 6172的速度差異很大!

+0

現在,這是新聞,從來不知道你可以這樣調整GC。我會在自己的代碼中給出一個鏡頭,非常感興趣,看看它會做什麼! – gjvdkamp 2011-06-06 12:15:38

0

垃圾收集器不分配存儲器。

聽起來更像是你分配了很多小的臨時對象和一些長壽命的對象,垃圾回收器花費了大量的時間垃圾收集臨時對象,所以你的應用程序不需要請求更多的操作系統內存。從.NET Framework 4 Advanced Development - Garbage Collection

只要地址空間是在託管堆中可用,運行時繼續爲新對象分配空間。但是,記憶不是無限的。最終垃圾收集器必須執行一個收集以釋放一些內存。

解決方案:不要分配大量的小臨時對象。Garbage Collection and Performance上的頁面也可能有幫助。

+0

我的應用程序的內存需求確實很大(幾千兆字節),但我有一個8GB內存和GC採集會話只發生一次,每分鐘左右,並且非常短 – Haggai 2010-05-26 15:23:39

+0

「GC採集會話每分鐘只發生一次,而且非常短「似乎與」大部分同步時間花費在等待GC線程完成內存分配上「相矛盾。 – 2010-05-31 15:26:07

0

您可以預先分配一堆對象,並將它們保存在用於單獨線程的組中。但是,您很可能無法從中獲得更好的表現。

垃圾收集器專門設計用於高效地處理小型短暫對象。如果將對象保存在一個池中,它們會很長壽,並且會在垃圾回收過程中存活下來,這意味着它們將被複制到第二代堆中。這種複製將比分配新對象更加昂貴。

+0

你的第一段完全是我目前的解決方案。當我在許多線程中多次重複使用這些對象時,我相信在這種情況下複製到第二代堆是無足輕重的。 我該如何檢查它是否是? – Haggai 2010-05-26 15:09:17