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

kb0*_*b00 5 .net c# 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();
Run Code Online (Sandbox Code Playgroud)

但是,我不确定这是使用该计数器的正确方法。在这篇文章:正确使用“% Time in GC”性能计数器中,答案说它应该像秒表一样使用,这就是我在操作之前调用 NextValue() 的原因。我不认为是这种情况,因为当我删除第一gcPerfCounter.NextValue()行时,它给了我相同的结果。

MSDN 文章介绍了“% Time in GC”性能计数器:

显示自上次垃圾收集周期以来执行垃圾收集所花费的时间百分比。 https://msdn.microsoft.com/en-us/library/w8f5kw2e(v=vs.110).aspx

这让我很困惑,因为我认为自从上次以来GC cycle我们在 . 中花费的时间为零GC。所以根据这个描述,这个值应该始终为零。

您能解释一下这个性能计数器在我的例子中的含义和正确使用吗?

Mar*_*age 5

我同意性能计数器的描述令人困惑。为了更好地理解它的含义,这里提供了.NET Framework 中性能计数器的完整描述,您提供了以下链接:

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

明确指出计数器在垃圾收集结束时更新。基于这个事实,我相信您可以使用以下时间线来更好地理解计数器:

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

            | 不在GC | 在气相色谱中 |
            +------------------+------+

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

该计数器针对每个垃圾收集周期进行计算Tend。参考时间线下方显示的时间间隔,该值是In GC时间占整个垃圾收集周期( Not in GCIn GC )总时间的百分比。

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

GC 时间百分比 = 100*(Tend1 - Tstart1)/(Tend1 - Tend0)

因此,计数器实际上给出了 GC 所花费的时间百分比,并且对计数器进行采样将给出基于前两次执行的 GC 的值。

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

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