【问题标题】:Reasons for seeing high "% Time in GC" in Perf Mon在 Perfmon 中看到高“% Time in GC”的原因
【发布时间】:2010-11-11 01:09:36
【问题描述】:

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

  1. 我是否纠正了这个过度?
  2. 如何找出路由导致 GC 峰值的原因?

【问题讨论】:

  • 需要注意的一点是,此性能计数器显示的是最后观察到的值,而不是连续平均值。它仅在每个 GC 周期结束时更新。
  • 它在一个自托管的 WCF 服务中。
  • 性能计数器在不断变化。这意味着什么?

标签: c# .net memory memory-management


【解决方案1】:

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

较高的“GC 时间百分比”通常是由分配然后丢弃数千或数百万个对象引起的。找出发生了什么的一个好方法是使用内存分析器工具。

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

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

确定分配的来源后,您需要检查代码并找出如何减少这些分配。虽然没有万能的答案,但我过去遇到的一些事情包括:

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

【讨论】:

    【解决方案2】:

    我是否纠正了这种过度?

    是的,你是对的

    如何找出路由导致 GC 峰值的原因?

    1.- 看看 PerfView

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

    另请参阅:Improving Managed Code Performance

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

    【讨论】:

    【解决方案3】:

    另一个原因可能是很多 gen-1 或 gen-2 集合,每个集合都需要更多时间,并且是由于挂在对象上的时间更长。

    我在网络应用程序中看到过这种情况,当有缺陷的对象挂在实际的页面对象上时 - 迫使页面与引用它们的其他对象一样长。

    断开对象和页面之间的链接(在这种情况下)导致 GC 下降到非常低的值。我们的网站现在有 100+ 次点击/秒,GC 时间通常为 1% 或更少。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-12-12
      • 2023-03-28
      • 1970-01-01
      • 2016-03-31
      • 1970-01-01
      • 2014-06-17
      • 2021-11-21
      相关资源
      最近更新 更多