在Perf Mon中看到“%GC时间”的原因

在Perf Mon中监控我们的应用程序时,我注意到GC的时间百分比在20-60%之间,而我们的应用程序执行长时间运行的过程(在30秒到1.5分钟之间变化)。 这对我来说似乎有些过分。 这提出了两个重要问题。

  1. 我纠正这个过分吗?
  2. 我可以采取的路线来弄清楚为什么GC会发生这么多?

是的,这确实听起来过分了。 减少GC的数量可能是减少应用程序运行时间的最佳步骤(如果这是您的目标)。

高“GC中的%时间”通常是通过分配然后丢弃数千或数百万个对象引起的。 找出正在发生的事情的好方法是使用内存分析器工具。

Microsoft提供免费的CLR Profiler 。 这将显示每个分配,但会使您的应用运行速度慢10-60倍。 您可能需要在较少的输入数据上运行它,以便它可以在合理的时间内完成分析。

一个伟大的商业工具是SciTech的.NET Memory Profiler 。 这会减少运行时间开销,并且可以免费试用。 通过在进程运行时获取多个快照,您可以找出经常分配(然后销毁)的对象类型。

一旦确定了分配源,就需要检查代码并找出如何减少这些分配。 虽然没有一个通用的答案,但我过去遇到的一些事情包括:

  • String.Split可以创建数百个小的短期字符串。 如果你正在进行大量的字符串操作,它可以通过逐个字符地处理它来帮助处理字符串。
  • 创建数千个小类(例如,大小不超过24个字节)的数组或列表可能很昂贵; 如果这些类可以被视为值类型,它可以(有时)大大改进事物以将它们更改为结构。
  • 创建数千个小数组可能会大量增加内存使用量(因为每个数组都有少量开销); 有时这些可以用一个大型数组替换并索引到它的子部分。
  • 拥有大量可终结的物品(特别是如果它们没有被处理掉)会给垃圾收集器带来很大的压力; 确保您正确处理所有IDisposable对象,并注意您自己的类型应该(几乎) 永远不会有终结器 。
  • Microsoft有一篇关于垃圾收集指南的文章,用于提高性能。

我纠正这个过分吗?

是的,你是对的

我可以采取的路线来弄清楚为什么GC会发生这么多?

1.-看看PerfView

PerfView是一种性能分析工具,可帮助隔离与CPU和内存相关的性能问题。

另请参阅: 提高托管代码性能

2.-查看是否在代码或第三方库中的任何位置调用GC.Collect或GC.WaitForPendingFinalizers。 后者可能导致高CPU利用率。

另一个原因可能是许多gen-1或gen-2集合,每个集合花费的时间更长,并且是由于长时间挂在物体上造成的。

我已经看到这种情况发生在Web应用程序中,当有错误的对象挂在实际页面对象上时 – 只要其他对象引用它们,就会强制页面生存。

打破对象和页面之间的链接(在本例中)会导致GC降至非常低的值。 我们的网站现在有100多次点击/秒,GC时间通常为1%或更低。