C# 防止在短时间内进行.NET垃圾收集

C# 防止在短时间内进行.NET垃圾收集,c#,performance,garbage-collection,C#,Performance,Garbage Collection,我有一个处理大量数据的高性能应用程序。它正在很短的时间内接收、分析和丢弃大量信息。这会导致我目前正在尝试优化的大量对象搅动,但也会导致第二个问题。当垃圾收集启动时,它会在清理过程中导致一些长时间的延迟(我所说的长时间是指10到100毫秒)。99%的时间这是可以接受的,但是对于大约1-2分钟的短暂时间窗口,我需要绝对确保垃圾收集不会导致延迟。我知道这段时间什么时候会提前发生,我只需要一种方法来确保垃圾收集不会在这段时间内发生。该应用程序是用C#编写的,使用.NET4.0框架,如果需要的话,可以同时

我有一个处理大量数据的高性能应用程序。它正在很短的时间内接收、分析和丢弃大量信息。这会导致我目前正在尝试优化的大量对象搅动,但也会导致第二个问题。当垃圾收集启动时,它会在清理过程中导致一些长时间的延迟(我所说的长时间是指10到100毫秒)。99%的时间这是可以接受的,但是对于大约1-2分钟的短暂时间窗口,我需要绝对确保垃圾收集不会导致延迟。我知道这段时间什么时候会提前发生,我只需要一种方法来确保垃圾收集不会在这段时间内发生。该应用程序是用C#编写的,使用.NET4.0框架,如果需要的话,可以同时使用托管和非托管代码

我的问题是,

  • 是否可以短暂暂停整个程序的垃圾收集
  • 是否可以使用System.GC.Collect()在我需要无垃圾收集的窗口之前强制垃圾收集,如果这样做,我将无垃圾收集多长时间
  • 人们对减少垃圾收集的需求有什么建议 注:该系统相当复杂,有许多不同的组件。我希望避免使用在程序的每个类上都必须实现自定义IDisposable接口的方法

    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文章,也有帮助:

    • (这就是为什么我们调用
      PrepareConstrainedRegions()
    注意:
    GCSettings.LatencyMode=GCLatencyMode.LowLatency
    只能在
    GCSettings.IsServerGC==false
    时设置<可以在
    App.config
    中更改代码>IsServerGC:

      <runtime>
        <gcServer enabled="false" />
      </runtime>
    
    
    
    .NET 4.6添加了两个新方法:仅此而已。

    这与每个类上的自定义
    IDisposable
    实现如何帮助解决您的问题有些重叠?这些对象在处理后仍然需要GC'ed,不是吗?
    IDisposable
    与垃圾收集无关。@LukeH-通过IDisposable接口的大量工作,我可以让每个对象检查应用程序是否处于关键时期,并在该时期结束之前阻止最终确定。这种方法需要付出大量的努力,并且有许多可能的缺点,但从理论上讲,它是可以使用的。一旦关键时期结束,将有大量的清理工作从巨大的突然完成的物体中进行。不是特别漂亮。@LukeH使用IDisposable接口,您可以在对象最终确定之前捕获它。此时,您将检查程序中的单例引用,以确定应用程序是否处于关键路径状态。如果是这样的话,请缩短完成时间,并将对象添加到清理队列中,以便以后处理。只要对象在该清理队列中被引用,它就不受GC的约束。关键路径状态完成后,清除队列中的所有对象都将被销毁并最终确定。老实说,我一点也不喜欢这样,我也不确定会不会有很大的副作用。这只是一个想法。如果你不介意的话,可以问几个问题。1.我知道关键事件将发生的一般时间段,但它将由从多播广播接收的数据元素触发。我想防止GC延迟接收该数据。你推荐什么?2.当您进入ConstrainedRegion或切换到LowLatency模式时,是否会影响性能?我一看到特定的数据项就可以这样做,而不会受到条目性能的影响吗?顺便说一句,非常有用的东西-谢谢。对于1,我想说的是,如果一般时间段很短,大约几秒钟,那么您可能可以将GC设置为
    LowLatency
    ,直到消息到达。再长一点,我想说你对我的知识无能为力。如果绝对不能有GC延迟,可以尝试在另一个进程中接收广播,然后将其封送到主进程,但这会使事情变得非常复杂。对于2,输入CER我认为在您输入和退出时会带来性能影响,但我从未测量过它,也没有自己设置延迟模式。感谢您提供的新信息。如果我能在这个问题相关的时候把它拿回来,那就太好了。希望它能帮助有同样问题的新人。