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

Sha*_*lle 9 .net c# memory memory-management

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

  1. 我纠正这个过度吗?
  2. 我可以采取哪些途径来弄清楚为什么GC会发生这么多?

Bra*_*ger 12

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

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

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

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

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

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