关于C#:如何避免在实时.NET应用程序中进行垃圾回收?

关于C#:如何避免在实时.NET应用程序中进行垃圾回收?

How to avoid garbage collection in real time .NET application?

我正在编写一个金融C#应用程序,该应用程序从网络接收消息,根据消息类型将它们转换为不同的对象,最后将应用程序业务逻辑应用于它们。

重点是在应用了业务逻辑之后,我确定我将不再需要该实例。我不想等待垃圾回收器释放它们,而是要显式"删除"它们。

在C#中是否有更好的方法,应该使用对象池来重用总是相同的一组实例,还是有更好的策略?

目标是避免垃圾收集在时间紧迫的过程中使用任何CPU。


请勿立即删除它们。为每个对象调用垃圾回收器是一个坏主意。通常,您真的根本不想弄乱垃圾收集器,即使时间紧迫的进程也是如此,如果它们如此敏感,它们就只是竞相等待的条件。

但是,如果您知道自己的应用在繁忙时段与轻负载时段之间,则可以在达到轻负载时段时尝试使用更通用的GC.Collect(),以鼓励在下一个繁忙时段之前进行清理。


查看此处:http://msdn.microsoft.com/zh-cn/library/bb384202.aspx

您可以告诉垃圾收集器您目前正在做一些重要的事情,它将对您有好处。


您打自己-使用对象池并重复使用这些对象。调用这些对象的语义将需要隐藏在工厂外观的后面。您需要以某种预定义的方式扩展池。每次达到极限时,大小可能都会增加一倍-高水位算法或固定百分比。我强烈建议您不要调用GC.Collect()。

当池中的负载足够低时,您可以收缩池,最终将触发垃圾回收-让CLR担心它。


尝试猜测垃圾收集器通常是一个非常糟糕的主意。在Windows上,垃圾收集器是一个世代的垃圾收集器,可以依靠它来提高效率。此一般规则有一些值得注意的例外-最常见的是一次发生的事件,您知道一个事实会导致许多旧对象死亡-一旦将对象提升到Gen2(寿命最长)他们倾向于闲逛。

在您提到的情况下,听起来好像您正在生成许多短期对象-这些将导致Gen0集合。无论如何,这些情况相对经常发生,并且是最有效的。如果愿意,可以通过具有可重用的对象池来避免它们,但是最好在执行此类操作之前确定GC是否存在性能问题-CLR分析器是执行此操作的工具。

请注意,不同的.NET框架中的垃圾收集器有所不同-在紧凑型框架(可在Xbox 360和移动平台上运行)上,它是非世代的GC,因此您必须拥有更多的能力注意程序会产生什么垃圾。


强制使用GC.Collect()通常是一个坏主意,让GC发挥其最大作用。听起来最好的解决方案是使用一个可以在必要时增长的对象池-我已经成功使用了这种模式。

这样,您不仅可以避免垃圾收集,而且还可以避免常规分配成本。

最后,您确定GC引起了您的问题吗?在实施任何节省性能的解决方案之前,您可能应该测量并证明这一点-您可能会导致自己不必要的工作!


"目标是避免垃圾收集在时间紧迫的过程中使用任何CPU "

问:如果时间紧迫,意味着您正在听一些深奥的硬件,您不能错过这个中断吗?

A:如果是这样,则C#不是要使用的语言,则需要使用汇编语言,C或C。

问:如果在关键时刻,您是指管道中有很多消息,而您又不想让垃圾收集器放慢速度吗?

A:如果是这样,您就不必担心了。从对象的声音来看,它们的寿命很短,这意味着垃圾回收器将非常有效地回收它们,而不会出现明显的性能延迟。

但是,唯一可以确定的方法就是对其进行测试,将其设置为运行一整夜以处理恒定的测试消息流,如果您的性能统计信息可以在GC启动时发现(并且即使您可以发现它,但如果它真的很重要,我会感到更加惊讶)。


应用程序强度有多大?我编写了一个应用程序,该应用程序以8KB的块捕获3个声卡(Managed DirectX,44.1KHz,立体声,16位),然后将3个流中的2个通过TCP / IP发送到另一台计算机。 UI会为3个通道的每个通道渲染一个音频电平表和(平滑的)滚动标题/艺术家。它可以在XP,1.8GHz,512MB等PC上运行。该应用使用大约5%的CPU。

我没有手动调用GC方法。但是我确实不得不调整一些浪费的东西。我使用RedGate的Ant探查器来细化那些浪费的部分。一个很棒的工具!

我想使用一个预先分配的字节数组池,但是托管DX程序集在内部分配字节缓冲区,然后将其返回给App。原来,我不必这样做。


对垃圾收集器的行为有一个很好的了解和感受,您将了解为什么不建议您在这里考虑什么。除非您真的很喜欢CLR花很多时间在内存中重新排列对象。

  • http://msdn.microsoft.com/zh-CN/magazine/bb985010.aspx
  • http://msdn.microsoft.com/zh-CN/magazine/bb985011.aspx

从它的声音看来,您似乎在谈论确定性终结(C中的析构函数),而C#中不存在。在C#中,最接近的东西是Disposable模式。基本上,您实现IDisposable接口。

基本模式是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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;
    }
}

如果绝对时间紧迫,那么您应该使用C / C之类的确定性平台。即使调用GC.Collect()也会生成CPU周期。

您的问题开始于关于要节省内存但要摆脱对象的建议。这是空间关键的优化。您需要决定自己真正想要的是什么,因为GC在优化这种情况方面比人为更好。


为什么每次收到消息时都不会创建对象的新实例,而是为什么不重用已经使用的对象?这样,您就不会与垃圾收集器进行对抗,堆内存也不会碎片化。**

对于每种消息类型,您可以创建一个池来保存未使用的实例。每当收到网络消息时,您都会查看消息类型,从适当的池中拉出一个等待的实例,然后应用您的业务逻辑。之后,将消息对象的实例放回其池中。

您很可能希望通过实例"延迟加载"池,以便轻松扩展代码。因此,您的池类将需要检测何时已拉空实例,并在派发空实例之前将其填满。然后,当调用代码将其放回池中时,它是一个真实实例。

** "对象池是一种使用模式,它允许对象被重用而不是分配和释放,这有助于防止堆碎片和昂贵的GC压缩。""

http://geekswithblogs.net/robp/archive/2008/08/07/speedy-c-part-2-optimizing-memory-allocations---pooling-and.aspx


池中每种类型的实例数量可能有限,然后重复使用已经完成的实例。池的大小取决于您将处理的消息量。


理论上,如果您的CPU负载过重或除非确实需要,GC不应运行。但是如果有必要,您可能只想将所有对象都保存在内存中(也许是单例实例),并且除非准备好就不要清理它们。这可能是保证GC运行的唯一方法。


推荐阅读

    linux实时读日志命令?

    linux实时读日志命令?,系统,信息,实时,工作,对比,管理,时间,命令,日志,平均,L

    linux实时读日志命令?

    linux实时读日志命令?,系统,信息,实时,工作,对比,管理,时间,命令,日志,平均,L

    linux命令实时显示?

    linux命令实时显示?,系统,实时,时间,信息,情况,命令,对比,电脑,名称,一致,lin

    查看linux类型命令?

    查看linux类型命令?,系统,信息,命令,状态,数据,数字,情况,地址,类型,文件,lin

    linux删除类型命令?

    linux删除类型命令?,系统,档案,命令,文件,名称,环境,数据,不了,目录,文件夹,

    linux中实时更新命令?

    linux中实时更新命令?,系统,数据,实时,管理,服务,命令,名字,工作,信息,软件,l

    查看linux库类型命令?

    查看linux库类型命令?,系统,工作,信息,状态,电脑,命令,工具,代码,地址,发行,

    linux网卡类型命令?

    linux网卡类型命令?,网络,系统,地址,信息,设备,状态,服务,名称,名字,网卡,如

    linux实时抓取命令?

    linux实时抓取命令?,网络,状态,信息,系统,服务,实时,命令,名称,情况,暂停,怎

    linux查看命令类型用?

    linux查看命令类型用?,信息,系统,情况,命令,实时,工作,设备,电脑,文件,类型,

    linux命令三种类型?

    linux命令三种类型?,工作,地址,系统,标准,时间,管理,命令,目录,信息,文件,lin

    linux命令和应用程序?

    linux命令和应用程序?,软件,系统,环境,管理,基础,情况,位置,电脑,工具,中心,

    linux实时看包命令?

    linux实时看包命令?,系统,实时,工作,命令,信息,数据,名称,文件,目录,标准,Lin

    python的垃圾回收机制

    python的垃圾回收机制,时间,技术,对象,系统,培训,名字,垃圾,标记,机制,内存

    Python垃圾回收

    Python垃圾回收,下来,时间,对象,情况,检测,代码,培训,垃圾,标记,阈值,Python

    python的数据类型

    python的数据类型,数字,较大,数据,培训,变量,表示,字符串,赋值,常量,小数,1.