4

我試圖測量我的應用程序中兩點之間在GC之間花了多少時間。就像這樣:測量「在GC中花費的時間百分比」

GC.Collect(); 
GC.WaitForPendingFinalizers(); 
GC.Collect(); 
gcPerfCounter.NextValue(); 

// This is the part that I would like to measure 
doStuff(); 

var timeSpentInGC = gcPerfCounter.NextValue(); 

但是,我不確定這是使用此計數器的正確方法。在這篇文章中:Correct use of "% Time in GC" performance counter答案表示它應該像秒錶一樣使用,這就是爲什麼我在操作之前調用NextValue()。我不認爲這是這種情況,因爲它給了我相同的結果,當我刪除第一個gcPerfCounter.NextValue()行。

MSDN文章說,有關性能計數器「在GC%時間」:

顯示已度過了自上次垃圾回收週期執行垃圾收集 的時間的百分比。 https://msdn.microsoft.com/en-us/library/w8f5kw2e(v=vs.110).aspx

它混淆了我,因爲我認爲自從上次GC cycle我們GC花費零時間。所以根據這個描述,這個值應該總是爲零。

你能向我解釋一下這個性能計數器的含義和正確使用情況嗎?

+0

這樣你不會得到任何有意義的結果,它只會在上一個GC循環中返回「GC Time%」。無法保證在運行'doStuff'時你會得到0,1個或更多的集合,並且不能保證這個集合會隨着時間的推移而重複。 – Groo

回答

3

我同意對性能計數器的描述很混亂。爲了更好地理解它計數這裏什麼是Performance Counters in the .NET Framework您提供一個鏈接到整個說明:

顯示已度過了自上次垃圾回收週期執行垃圾收集的時間的百分比。該計數器通常表示垃圾收集器代表應用程序收集和壓縮內存所做的工作。該計數器僅在每個垃圾收集結束時更新。這個計數器不是一個平均值;其價值反映了最近的觀測值。

明確指出計數器在垃圾回收結束時更新。基於這一事實,我相信你可以使用下面的時間表,以更好地理解計數器:

 
     GC0      GC1 
----+-------+------------------+-------+---- 
Tstart0 Tend0    Tstart1 Tend1 

      | Not in GC  | In GC | 
      +------------------+-------+ 

垃圾回收週期是在說明中所涉及到的是間隔[Tend0, TEnd1]。通過這個定義,描述中的第一句變得更有意義。

對於每個垃圾收集週期,計數器的計算值爲Tend。參考時間線下面顯示的時間間隔,數值是時間在GC佔整個垃圾收集週期(不在GC在GC中)的總時間的百分比。

或者更正式,在Tend1性能計數器的值是:

 
% Time in GC = 100*(Tend1 - Tstart1)/(Tend1 - Tend0) 

所以櫃檯有板有眼在GC上花費的和採樣計數器將給出基於前兩個GC的值的百分比時間執行。

要檢查這一點,你可以試着品嚐櫃檯%時間在GC以及三個#X一代收藏櫃檯看到,當其他三個計數器的一個改變第一計數器只改變(如在兩個樣品之間進行GC)。

這個計數器可以用來檢查一個軟件是否花了過多的時間做垃圾收集。但是,由於計數器僅反映了最後一次垃圾收集週期所花費的時間,因此您必須隨時間對該計數器進行抽樣以正確進行此檢查。