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

时间:2011-04-13 00:28:35

标签: .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不在Win2k3服务器中显示.Net工具。)

2 个答案:

答案 0 :(得分:28)

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

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

  1. 调用 System.Runtime.GCSettings.IsServerGC 属性
  2. 使用WinDbg附加到进程并使用命令“!sos.threads”检查有多少GC线程而没有引号和(根据以下标准)...
  3. 你没有说你有什么样的应用程序。如果您正在运行控制台应用程序,WinForm应用程序或Windows服务,您将获得Workstation GC。仅仅因为您在服务器操作系统上运行并不意味着您将获得GC的服务器版本。如果您的应用程序未托管在多进程计算机上,则默认情况下将获得Workstation GC - Concurrent。如果您的应用程序托管在多进程计算机上,则默认情况下将获得ServerGC。

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

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

    Workstation GC

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

    Workstation GC - 并发

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

    服务器GC

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

    无论GC模式如何,每个托管进程只有1个终结器线程。即使在并发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):
      • 如有必要,允许与背景GC同时进行短暂的GC
      • 性能更快
    • 服务器GC始终阻止线程以收集任何代

    在CLR 4.5中,事情只有一点点变化......再次

    • 后台服务器GC:
      • 服务器GC不再阻止。相反,它使用专用的背景GC 可以与用户代码同时运行的线程 - 请参阅MSDN: Background Server 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线程免费列表'。此功能应有助于缓解此问题。

答案 1 :(得分:1)

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

<configuration>
   <runtime>
      <gcServer enabled="false"/>
   </runtime>
</configuration>

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

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