有多少垃圾收集太多

Joh*_*est 6 .net garbage-collection azure

我们的Web应用程序有数百个用户,并且(一如既往)主要由旧代码组成。

迁移到Azure后,我们可以查看和衡量比以前更多的指标。我们遇到了性能问题,我发现我们的垃圾回收正在不断进行(如“性能计数器”部分下的Web应用程序的“诊断”标签中所测量)。一分钟内,我们就能得到以下数字:

  • 90160 GEN 0垃圾收集
  • 76910第1代垃圾回收
  • 75110 GEN 2垃圾收集

这仅用于18580个HTTP请求,因此平均而言,我们有:

  • 每个请求4,85 GEN 0垃圾回收
  • 每个请求4,13 GEN 1垃圾收集
  • 每个请求4,04 GEN 2垃圾收集

即使请求数量保持不变,这些数字仍在增加(请参见图表)

GC疯狂

我的问题/评论是:

  • 这些数字是GC清除的对象数量,还是GC必须处于活动状态的次数?
  • 在这样的负载下,多少GC将被视为“正常”,非常清楚没有一个是完美的答案,但是实际上...
  • 即使请求数量保持不变,GC收集的数量又如何像这样增加呢?

约翰,非常感谢你


更新1:30/06/2018 @ 8:16 UTC + 2

在更新了应用程序见解以更紧密地监视垃圾收集之后,我发现性能大打折扣。首先,这是在GC中花费的平均时间百分比:

GC中的平均时间大约为百分之四点五

平均大约有4.5%的时间(但在此期间夜间处于非活动状态),平均大约有10%的时间偷看。然后,我想可视化应用程序处于GC模式的最长时间,而我几乎掉下了椅子:

GC中的最长时间约为99%

这可能是错误的图像。但这说明我们的代码必须等待很多时间!我们确实必须解决此问题。

Nip*_*tha 0

让我们先学习一些适合几代人的东西:

第 0 代。这是最年轻的一代,包含短暂的对象。短期对象的一个​​例子是临时变量。垃圾收集在这一代中发生得最为频繁。

新分配的对象形成新一代对象,并且隐式为第 0 代集合,除非它们是大对象,在这种情况下,它们位于第 2 代集合中的大对象堆上。

大多数对象在第 0 代中被回收用于垃圾收集,并且不会保留到下一代。

第 1 代。这一代包含短寿命对象,并充当短寿命对象和长寿命对象之间的缓冲区。

第2代。这一代包含长寿命的对象。长寿命对象的一个​​示例是服务器应用程序中的对象,该对象包含在进程持续时间内有效的静态数据。

在垃圾收集中未回收的对象称为幸存者,并被提升到下一代。在第 0 代垃圾回收中幸存下来的对象将提升到第 1 代;在第 1 代垃圾回收中幸存下来的对象将提升到第 2 代;在第 2 代垃圾回收中幸存下来的对象仍保留在第 2 代中。

当垃圾收集器检测到一代中的生存率较高时,它会增加该一代的分配阈值,因此下一次收集会获得大量的回收内存。CLR 不断平衡两个优先级:不让应用程序的工作集变得太大,以及不让垃圾收集花费太多时间。

临时段的大小取决于系统是 32 位还是 64 位以及它运行的垃圾收集器的类型。默认值如下表所示。

32位 64位
工作站气相色谱 16MB 256MB
服务器GC 64MB 4GB
具有 > 4 个逻辑 CPU 的服务器 GC 32MB 2GB
具有 > 8 个逻辑 CPU 的服务器 GC 16MB 1GB

临时段可以包括第二代对象。第 2 代对象可以使用多个段(根据进程需要和内存允许的数量)。

从临时垃圾回收中释放的内存量仅限于临时段的大小。释放的内存量与死亡对象占用的空间成正比。

参考:https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/fundamentals