在短时间内防止.NET垃圾收集

时间:2011-05-15 01:17:17

标签: c# performance garbage-collection

我有一个处理大量数据的高性能应用程序。它在很短的时间内接收,分析和丢弃大量信息。这导致我正在尝试优化的大量对象流失,但它也会导致次要问题。当垃圾收集开始时它可以导致一些长时间的延迟,因为它清理了一些东西(长的意思是10到100毫秒)。 99%的时间这是可以接受的,但对于大约1-2分钟的短暂时间窗口,我需要绝对确定垃圾收集不会导致延迟。我知道这些时间段何时会事先发生,我只需要一种方法来确保在此期间不会发生垃圾收集。该应用程序使用.NET 4.0 Framework以C#编写,如果重要,则使用托管代码和非托管代码。

我的问题是;

  1. 是否可以暂时暂停整个程序的垃圾收集?
  2. 是否可以使用System.GC.Collect()在我需要垃圾收集的窗口之前强制进行垃圾收集,如果我做垃圾收集有多长时间?
  3. 人们对减少整体垃圾收集的需求有什么建议?
  4. 注意 - 这个系统相当复杂,有很多不同的组件。我希望避免采用我必须在程序的每个类上实现自定义IDisposable接口的方法。

2 个答案:

答案 0 :(得分:76)

.NET 4.6为此添加了两个新方法:GC.TryStartNoGCRegionGC.EndNoGCRegion

答案 1 :(得分:72)

GCLatencyMode oldMode = GCSettings.LatencyMode;

// Make sure we can always go to the catch block, 
// so we can set the latency mode back to `oldMode`
RuntimeHelpers.PrepareConstrainedRegions();

try
{
    GCSettings.LatencyMode = GCLatencyMode.LowLatency;

    // Generation 2 garbage collection is now
    // deferred, except in extremely low-memory situations
}
finally
{
    // ALWAYS set the latency mode back
    GCSettings.LatencyMode = oldMode;
}

这将允许您尽可能多地禁用GC。在下列情况之前,它不会执行任何大型对象集合:

  • 您致电GC.Collect()
  • 您将GCSettings.LatencyMode设置为LowLatency
  • 以外的其他内容
  • 操作系统向CLR发送低内存信号

执行此操作时请务必小心,因为当您处于try块时,内存使用量可能会非常快。如果GC正在收集,它会出于某种原因这样做,如果你的系统有大量内存,你应该认真考虑这个。

在参考问题三时,如果您通过文件系统I / O或网络接收信息,也许可以尝试重用字节数组之类的对象?如果您要将这些信息解析为自定义类,请尝试重复使用它们,但如果不了解您正在做什么,我就无法给出太多好的建议。

以下是一些可以提供帮助的MSDN文章:

注意: GCSettings.LatencyMode = GCLatencyMode.LowLatency只能在GCSettings.IsServerGC == false时设置。可以在IsServerGC

中更改App.config
  <runtime>
    <gcServer enabled="false" />
  </runtime>