2011-04-10 70 views
2

我們的多線程應用程序做了冗長的計算循環。平均來說,它需要大約29秒才能完成一個完整週期。在那段時間內,.NET性能計數器% time in GC佔到8.5%。它全部由Gen 2系列產品組成。什麼會導致性能改進?時間GC,彙集

爲了提高性能,我們實現了我們的大對象池。我們實現了100%的娛樂率。整個週期現在平均只需要20秒。 GC中的%時間顯示0.3 ... 0.5%之間。現在,GC只執行Gen 0集合。

讓我們假設,該池是有效地實現,而忽略附加花費的時間執行。比我們的表現改善了大約33%。這與以前的8.5%的GC值有什麼關係?

我有一些假設,我希望可以確認,調整和修訂:

1)(如果我沒有看錯),並測量2次的關係「在GC時間」跨越:

  • 2個GC週期和用於最後一個完整GC週期
  • 時間之間的時間,該值被包括在第一範圍。什麼是不包括在第二時間跨度

,將停止和重新啓動工作線程阻塞GC的開銷。但是,這怎麼可能達到整個執行時間的20%呢?

2)通常阻斷線程GC可以胎面之間引入爭用?這只是一個想法。我無法通過VS併發分析器來確認。

3)與此相反,它可以確認頁面未命中(數性能計數器:內存 - 頁面錯誤秒)> /爲比用於與應用的UNPOOLED應用(25.000每秒)顯著更高低GC率(每秒200次)。我可以想象,這也會帶來很大的改善。但是,什麼可以解釋這種行爲?難道是因爲頻繁的分配會導致虛擬內存地址空間中的一個更大的區域被使用,因此難以保存到物理內存中?那麼如何衡量這個原因呢?

BTW:GCSettings.IsServerGC =假,.NET 4.0,64位,Win7上,4GB,英特爾酷睿i5運行。 (很遺憾的大問題..;)

+2

我很猶豫回答你的問題,因爲缺少很多信息給你一個真正的答案。 無論如何 - 總體性能改進*可能是由於: 1.減少GC時間(計算爲〜8.0%=〜2秒)2.您所有的時間不必重新創建那些真正大的物體,因爲它們現在已經有效地彙集了。這可能會非常昂貴,而且如果您將8.5%的時間花費在GC上,可能會非常昂貴。 – NightDweller 2011-04-10 16:51:09

+0

@NightDweller感謝您的評論。這些對象是'唯一'的大數組。彙集它們所節省的唯一時間是最初清除它們所需的時間(將其元素設置爲0)。另一方面,我認爲在任何託管堆分配中,預計成本更高。 – user492238 2011-04-10 17:04:23

+1

在某些情況下分配可能會很昂貴 - 如果您經常重新分配,並且需要長時間連續的內存塊,這些內存塊可能會因爲碎片而變得很少。但是我必須承認它似乎並不全是可能的。 您是否嘗試在代碼上運行一個分析器? (之前/之後),應該給你一個非常明確的答案,以改善... – NightDweller 2011-04-10 21:40:16

回答

2

預分配的對象,來改善併發線程不再有進入全球鎖保護的垃圾回收堆中分配的對象。該鎖保持很短的時間,但顯然你分配了很多對象,所以線程不會鎖定鎖。

性能計數器「關於在GC時間」措施的CPU時間百分比花在收集,而不是執行常規代碼。如果有很多gen#2集合,並且分配對象的速度非常快,以至於後臺收集無法繼續並且線程必須被阻止,則可以獲得大數目。擁有更多線程會使情況變得更糟,您可以分配更多。

+0

請注意,全局分配鎖不用於所有虛擬機。我記得新的Mono GC爲每個線程分配了不同的部分。 – Dykam 2011-04-10 18:12:12

+0

gcserver版本也是如此。 – 2011-04-10 18:24:40

3

然後我們得到了約33%的績效改進 。那怎麼 涉及到爲 8.5%GC前值?

通過合併,您還可以節省花費在new上的時間,這可能相當可觀,但我不會花時間來平衡數字。

而不是「在馬上看禮物馬」,爲什麼不繼續尋找其他「瓶頸」?

當您刪除一個性能問題時,由於分母較小,因此您可以讓其他人佔用較大的時間百分比。 所以他們更容易找到,只要你知道如何尋找他們

Here's an example, and a method. 您清除了一個大問題。 這使得下一個百分比更大,所以你清理一個。 沖洗並重復。 它可能需要花費很少的時間,以至於需要在它周圍包裹一個臨時外部循環,只是爲了使其花費足夠長的時間來進行調查。 你繼續這樣走下去,逐漸讓這個程序花費越來越少的時間,直到你達到收益遞減。

這就是如何使代碼快速。

+0

謝謝,感謝您的反饋。但是這錯過了這個問題?我並不關心任何*特定應用程序的性能,而是希望更深入地瞭解導致性能改進的根本原因。通過學習,我可以在將來節省更多時間,立即防止這些瓶頸(我現在甚至沒有想到它們存在)。 – user492238 2011-04-11 03:57:13

+0

@ user492238:正如我所說的,當您使用池回收使用的對象時,不僅可以節省GC時間,還可以節省「新」時間。我經常看到程序花費大量時間1)分配內存並運行初始化程序,或者2)運行析構程序。這就是你在儲存時保存的內容。 *然而,*無論你和我在避免緩慢方面有多好,*它都會發生*。因此,學習如何找到它更爲重要,以便在發生之後以及之前將其刪除。 – 2011-04-11 12:08:34

相關問題