C# 如何避免实时.NET应用程序中的垃圾收集?
我正在编写一个金融C#应用程序,它接收来自网络的消息,根据消息类型将它们转换为不同的对象,并最终在它们上应用应用应用程序业务逻辑 关键是,在应用了业务逻辑之后,我非常确定我再也不需要这个实例了。我不想等待垃圾收集器释放它们,而是想显式地“删除”它们 在C#中是否有更好的方法来实现这一点,我应该使用对象池来始终重用同一组实例,还是有更好的策略C# 如何避免实时.NET应用程序中的垃圾收集?,c#,.net,garbage-collection,real-time,finance,C#,.net,Garbage Collection,Real Time,Finance,我正在编写一个金融C#应用程序,它接收来自网络的消息,根据消息类型将它们转换为不同的对象,并最终在它们上应用应用应用程序业务逻辑 关键是,在应用了业务逻辑之后,我非常确定我再也不需要这个实例了。我不想等待垃圾收集器释放它们,而是想显式地“删除”它们 在C#中是否有更好的方法来实现这一点,我应该使用对象池来始终重用同一组实例,还是有更好的策略 目标是避免垃圾收集在时间关键的进程中使用任何CPU。不要立即删除它们。为每个对象调用垃圾收集器是个坏主意。通常情况下,您根本不想弄乱垃圾收集器,即使时间关键
目标是避免垃圾收集在时间关键的进程中使用任何CPU。不要立即删除它们。为每个对象调用垃圾收集器是个坏主意。通常情况下,您根本不想弄乱垃圾收集器,即使时间关键型进程也只是等待发生的竞争条件,如果它们如此敏感的话 但是,如果您知道您的应用程序将处于忙负载期与轻负载期,那么当您到达一个轻负载期时,您可以尝试使用更通用的GC.Collect(),以鼓励在下一个忙负载期之前进行清理。请看这里:
你可以告诉垃圾收集器你正在做一些关键的事情,它会尽力对你友好。你可以在一个池中有有限数量的每种类型的实例,并重用已经完成的实例。池的大小取决于您要处理的消息量。强制执行GC.Collect()通常是个坏主意,让GC做它最擅长的事情。听起来最好的解决方案是使用一个对象池,如果需要的话,可以增加这些对象-我已经成功地使用了这种模式 这样不仅可以避免垃圾收集,还可以避免常规分配成本
最后,您确定GC给您带来了问题吗?在实施任何性能节省解决方案之前,您可能应该测量并证明这一点-您可能会给自己带来不必要的工作 理论上,如果您的CPU负载很重,或者除非确实需要,否则GC不应该运行。但如果必须这样做,您可能希望将所有对象都保存在内存中,可能是一个单实例,并且除非准备好了,否则永远不要清理它们。这可能是保证GC运行的唯一方法。如果它是绝对时间关键的,那么您应该使用确定性平台,如C/C++。即使调用GC.Collect()也会产生CPU周期
你的问题从一个建议开始,即你想节省内存,但要清除对象。这是一个空间关键优化。你需要决定你真正想要的是什么,因为GC比人更擅长优化这种情况。对垃圾收集器的行为有一个很好的理解和感受,你就会明白为什么这里的想法不被推荐。除非你真的喜欢CLR花很多时间重新排列内存中的对象
试图猜测垃圾收集器通常是一个非常糟糕的主意。在Windows上,垃圾收集器非常高效,可以信赖。这条一般规则有一些值得注意的例外情况——最常见的是一次性事件的发生,你知道这会导致很多旧对象死亡——一旦对象升级到Gen2(寿命最长的),它们往往会挂起 在您提到的例子中,您听起来好像正在生成许多短期对象—这些将导致Gen0集合。无论如何,这种情况发生得相对频繁,而且效率最高。如果愿意的话,您可以通过拥有一个可重用的对象池来避免这些问题,但最好在采取此类操作之前确定GC是否是一个性能问题-CLR探查器是执行此操作的工具 需要注意的是,垃圾收集器在不同的.NET框架上是不同的——在compact框架上(在Xbox 360和移动平台上运行)这是一个非代GC,因此您必须更加小心程序生成的垃圾。您自己动手——使用对象池并重用这些对象。对这些对象的调用的语义需要隐藏在工厂外观后面。您需要以某种预定义的方式扩展池。也许每次它达到极限时都会加倍——一个高水位算法,或者一个固定的百分比。我强烈建议您不要调用GC.Collect()
当池中的负载足够低时,您可能会收缩池,这最终会触发垃圾收集——让CLR来担心它。听上去,您似乎在谈论确定性终结(C++中的析构函数),这在C#中是不存在的。最近的
public class MyClass: IDisposable
{
private bool _disposed;
public void Dispose()
{
Dispose( true );
GC.SuppressFinalize( this );
}
protected virtual void Dispose( bool disposing )
{
if( _disposed )
return;
if( disposing )
{
// Dispose managed resources here
}
_disposed = true;
}
}