确定正在运行的垃圾收集器

Sup*_*man 9 .net garbage-collection

我正在Windows Server 2003 x64(2x Xeon 4核心触发器)上运行一个大型.net 4.0 x86应用程序,并且遇到了我的应用程序〜每天2-3次冻结30秒,然后恢复正常运行的问题.该应用程序每周只重启一次,消耗400-800 MB的内存,所以我假设这些冻结是垃圾收集.我只看到日志中的冻结,而不是现场,或者我会检查任务管理器确认.

我试图找出哪个.Net 4 GC正在运行,以及如何将GC切换到新的并发背景gc(如果不是),或者如何确认这些实际上是GC(Procmon不显示.Net) Win2k3服务器中的仪器).

Dav*_*ack 29

我在我的博客上重新发布了这个答案:http://dave-black.blogspot.com/2012/04/how-to-determine-which-garbage.html

您可以通过2种方法确定您正在运行的GC版本:

  1. 调用System.Runtime.GCSettings.IsServerGC属性
  2. 使用WinDbg附加到进程并使用命令"!sos.threads"检查有多少GC线程而没有引号和(根据以下标准)...

你没有说你有什么样的应用程序.如果您正在运行控制台应用程序,WinForm应用程序或Windows服务,您将获得Workstation GC.仅仅因为您在服务器操作系统上运行并不意味着您将获得GC的服务器版本.如果您的应用程序未托管在多进程计算机上,则默认情况下将获得Workstation GC - Concurrent.如果您的应用程序托管在多进程计算机上,则默认情况下将获得ServerGC.

默认情况下,任何IIS或CLR自托管应用程序都将以ServerGC模式运行.

以下内容适用于任何给定的.NET托管进程:

工作站GC

  • uni-proc机器
  • 始终挂起线程
  • 1个短暂的GC堆(SOH),1个LOH GC堆
  • 在触发GC的线程上运行
  • 线程优先级与触发GC的线程相同

工作站GC - 并发

  • 仅在Gen2/LOH中同时运行(完整集合)
  • 与服务器模式互斥
  • 稍大的工作集
  • 如果一段时间后没有使用,GC线程将过期
  • 1个短暂的GC堆(SOH),1个LOH GC堆
  • 专用GC线程
  • 线程优先级为Normal

服务器GC

  • 分段大小更大
  • 比Workstation GC更快
  • 始终挂起线程
  • 每个逻辑处理器的1个临时GC堆(SOH)(包括超线程),每个逻辑处理器1个LOH GC堆(包括超线程)
  • 专用GC线程
  • 线程优先级为THREAD_PRIORITY_HIGHEST

无论GC模式如何,每个托管进程只有1个Finalizer线程.即使在并发GC期间,托管线程也会被挂起(阻塞)两次以执行GC的某些阶段.

一个鲜为人知的事实是,即使您尝试设置GC的服务器模式,也可能无法在Server GC中运行; GC最终确定哪种模式最适合您的应用,如果确定您的ServerGC设置会对您的应用产生负面影响,则会覆盖您的设置.此外,在单处理器计算机上运行的任何托管CLR应用程序都将覆盖任何手动GC设置 - 在这种情况下,CLR将始终使用Workstation GC模式.

在CLR 4.0中,事情只有一点点变化

  • Concurrent GC现在是Background GC
  • 背景GC仅适用于Workstation GC
  • 旧(并行GC):
    • 在完整GC允许分配期间,直到短暂段大小结束
    • 否则,挂起所有其他线程
  • 新(背景GC):
    • 如有必要,允许与Background GC同时进行短暂的GC
    • 性能要快得多
  • 服务器GC始终阻止线程以收集任何代

在CLR 4.5中,事情只会再次发生变化

  • 后台服务器GC:
    • 服务器GC不再阻止.相反,它使用可与用户代码同时运行的专用后台GC线程 - 请参阅MSDN:后台服务器GC

因此,在.NET 4.5+,所有的应用程序现在有背景GC 提供给他们,无论他们使用何种GC.

.NET 4.7.1 GC改进

.NET Framework 4.7.1引入了垃圾收集(GC)中的更改以提高分配性能,尤其是对于大对象堆(LOH)分配.这是由于架构更改将堆的分配锁分为2,小对象堆(SOH)和LOH.进行大量LOH分配的应用程序应该看到分配锁争用的减少,并且看到更好的性能.这些改进允许LOH分配,而背景GC(BGC)正在扫描SOH.通常,LOH分配器在满足分配存储器的请求之前等待BGC扫描过程的整个持续时间.这可能会影响性能.您可以在PerfView的GCStats中观察到此问题,其中存在"LOH分配暂停(由于后台GC)> 200毫秒事件"表.暂停的原因是'等待BGC线程免费列表'.


Han*_*ant 2

您运行在服务器版本的 Windows 上,默认情况下您将获得服务器版本的垃圾收集器。它不进行后台收集,垃圾由多个线程收集,因此偶尔可观察到的暂停并不罕见。您可以使用 app.exe.config 文件强制使用工作站版本:

<configuration>
   <runtime>
      <gcServer enabled="false"/>
   </runtime>
</configuration>
Run Code Online (Sandbox Code Playgroud)

另请查看GC.RegisterForFullGCNotification()方法的文档,了解处理暂停副作用的方法。

.NET 4.5 版将支持服务器 GC 的后台收集。

  • 仅仅因为您在 Windows 的“服务器”版本上运行 .NET 应用程序并不意味着您将获得 GC 的服务器版本。请参阅下面我的回答以获取解释。 (3认同)