调试性能问题,其中一台服务器使用的CPU比预期的多,我目前专注于GC,因为GC中的%时间似乎在30左右,我发现它太高了。
此外,我注意到一种模式,CPU使用率逐渐上升,直到每晚午夜游泳池回收。 LOH大小也在不断上升(我怀疑它是因为我们缓存了用户信息),这让我认为不断增长的LOH是CPU的原因,并且GC的百分比正在逐渐增加,直到回收。我也注意到了很多gen2系列。
看看这张图,我发现了两件事:
1)GC的模式是否正常?我认为第二代的收集次数要少得多。
2)17:40发生了什么?服务器有两个正在运行的应用程序池(一个只是一个虚拟网站,一个正在完成所有工作),对我而言,它看起来像是在17:40切换位置,没有回收或似乎发生了任何事情。
GC和分配B /秒的时间跟随一个奇怪但上升的模式:
答案 0 :(得分:0)
我不确定17:40发生了什么。
但是,这种模式对于GC来说是正常的。收集Gen2的次数将减少很多次,收集的Gen0将超过Gen1,收集的Gen1将超过Gen.2。
只是介绍GC的工作原理。
对于托管对象,有三个小对象堆(SOH)和一个大对象堆(LOH)。
大对象堆(LOH)
大于85KB的物体将立即进入LOH。如果您有太多大型物体,则存在一些风险。这是一个不同的讨论,有关详细信息,请查看The Dangers of the Large Object Heap
小对象堆(SOH):Gen0,Gen1,Gen2
垃圾收集器使用一种聪明的算法仅在需要时执行垃圾收集器。完全垃圾收集过程是一项昂贵的操作,不应该经常发生。因此,它已将其SOH分为三个部分,因为您已经注意到每个Gen都有指定的内存量。
每个小对象(<85KB)最初都会转到Gen0。当Gen0已满时,垃圾收集仅对Gen0执行。它检查Gen0中的所有实例并清除/释放任何不必要的对象(未引用的,超出范围或处置的对象)使用的内存。然后它将所有必需的(已使用的)实例复制到Gen1。
即使您执行以下操作,上述过程实际上也会发生:(不需要手动调用)
// Perform a collection of generation 0 only.
GC.Collect(0);
通过这种方式,垃圾收集器首先清除为短期实例分配的内存(不可变的字符串,方法中的变量或较小的范围)。
当GC在一个阶段继续执行此操作时,Gen1溢出。然后它对Gen1执行相同的操作。它清除Gen1中所有不必要的内存,并将所有必需的内存复制到Gen2。
当您在下面手动执行(不需要手动调用)
时,会发生上述过程// Perform a collection of all generations up to and including 1.
GC.Collect(1);
当GC在一个阶段继续执行此操作时,如果Gen2溢出,它会尝试清除Gen2。
即使您在下面手动执行(不需要手动执行)
,也会发生上述过程// Perform a collection of all generations up to and including 2.
GC.Collect(2);
如果需要从Gen1复制到Gen2的内存量大于Gen2中可用的内存量,GC会抛出内存不足。