测量“在GC中花费的时间百分比”

时间:2016-02-29 08:03:22

标签: c# .net garbage-collection performancecounter memory-profiling

我正在尝试测量应用程序中两点之间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中花了零时间。因此,根据此描述,此值应始终为零。

你能解释一下这个性能指标的含义和正确用法吗?

1 个答案:

答案 0 :(得分:3)

我同意性能计数器的描述令人困惑。为了更好地理解这里重要的是Performance Counters in the .NET Framework中您提供了以下链接的完整描述:

  

显示自上次垃圾回收周期以来执行垃圾回收所花费的时间百分比。此计数器通常表示垃圾收集器为代表应用程序收集和压缩内存所做的工作。此计数器仅在每个垃圾回收结束时更新。这个计数器不是平均值;它的值反映了最后观察到的值。

清楚地说明计数器在垃圾收集结束时更新。基于这一事实,我相信您可以使用以下时间表来更好地理解计数器:

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

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

描述中引用的垃圾收集周期是区间[Tend0, TEnd1]。通过这个定义,描述中的第一句话变得更有意义。

对于每个垃圾收集周期,计数器的计算结果为Tend。参考时间轴下方显示的时间间隔,该值是 In GC 中的时间占整个垃圾收集周期总时间的百分比(不在GC >在GC中)。

或者更正式地,在Tend1,性能计数器的值是:

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

因此,计数器确实给出了在GC中花费的百分比时间,并且计数器的采样将根据之前执行的两次GC给出值。

要检查这一点,您可以尝试对计数器%Time in GC 以及三个#Gen X Collections 计数器进行采样,并看到第一个计数器仅在其他三个计数器中的一个发生变化(例如,两个样本之间进行了GC)。

此计数器可用于检查软件是否花费不成比例的时间进行垃圾收集。但是,由于计数器仅反映最后一次垃圾收集周期所花费的时间,因此您必须随着时间的推移对计数器进行抽样以正确进行此检查。