代码之家  ›  专栏  ›  技术社区  ›  Shane Courtrille

在性能监视器中看到高百分比GC时间的原因

  •  9
  • Shane Courtrille  · 技术社区  · 15 年前

    在性能监控中监控我们的应用程序时,我注意到当我们的应用程序执行一个长时间运行的过程(30秒到1.5分钟不等)时,GC中的时间百分比在20%到60%之间。我觉得这有点过分。这提出了两个重要问题。

    1. 我说得对吗?
    2. 我可以走的路线来弄清楚为什么会发生这么多GC?
    3 回复  |  直到 6 年前
        1
  •  12
  •   Bradley Grainger    15 年前

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

    GC中的高百分比时间通常是由分配然后丢弃数千或数百万个对象引起的。一个很好的方法就是使用内存分析器工具。

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

    一个伟大的商业工具是科技 .NET Memory Profiler . 这就减少了运行时开销,并且提供了一个免费的试用版。通过在进程运行时拍摄多个快照,您可以了解频繁分配(然后销毁)的对象类型。

    一旦确定了分配的来源,您就需要检查代码并找出如何减少这些分配。虽然没有一个适合所有答案的尺寸,但我过去遇到的一些问题包括:

    • split可以创建数百个短命的小字符串。如果您要进行大量的字符串操作,可以通过逐个字符地遍历字符串来帮助处理字符串。
    • 创建数千个小类(例如,小于24字节)的数组或列表可能代价高昂;如果这些类可以被视为值类型,则可以(有时)极大地改进将它们更改为结构的方法。
    • 创建数千个小数组可以大大增加内存使用量(因为每个数组的开销很小);有时可以用一个大数组替换这些数组,并将其索引到其中的一个子部分。
    • 拥有大量可终结的对象(尤其是在不处理它们的情况下)会给垃圾收集器带来很大的压力;确保正确地处理所有IDisposable对象,并注意您自己的类型应该(几乎) never have finalizers .
    • 微软有一篇文章 Garbage Collection Guidelines 以提高性能。
        2
  •  2
  •   Alex Nolasco    6 年前

    我说得对吗?

    是的,你是对的

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

    1.-看一看 PerfView

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

    参见: Improving Managed Code Performance

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

        3
  •  1
  •   n8wrl    15 年前

    另一个原因可能是大量的gen-1或gen-2集合,每一个都需要花费更多的时间,这是由于长时间地挂在对象上造成的。

    我在Web应用程序中看到过这样的情况,当有缺陷的对象挂在实际的页面对象上时——强制页面和引用它们的其他对象一样长。

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