c#内存泄漏??第0代和第1代的性能不断提高-这意味着什么?

本文关键字:什么 意味着 泄漏 内存 0代 1代 性能 | 更新日期: 2023-09-27 18:13:54

我正在为一个多线程应用程序使用c# 2.0,该应用程序每秒从非托管dll接收至少1000个回调,并定期从套接字发送消息。GUI仍然在主线程上。

我的应用程序主要在启动时创建对象,并在短时间内周期性地在执行期间创建对象。

我遇到的问题是周期性的延迟峰值(通过在开始和结束时对函数进行时间戳来测量),我认为这在GC运行时发生。

我运行了perfmon,下面是我的观察结果…

Gen0堆大小是平坦的,每隔几秒出现一个峰值,具有周期性峰值。

Gen1 Heap Size始终处于滚动状态。Up and down

Gen2 Heap Size遵循一个循环。它一直增加,直到一段时间变平,然后下降。

Gen 0和Gen 1的收集总是以1到5个单位的范围增加。第2代集合是常量

c#内存泄漏??第0代和第1代的性能不断提高-这意味着什么?

我建议使用内存分析器来了解您是否有真正的内存泄漏。有许多可用的工具,它们将允许您快速隔离任何问题。

垃圾收集器是自适应的,将根据应用程序使用内存的方式修改其运行频率。只看生成堆大小对找出问题的根源并没有什么帮助。再次质疑它是如何工作的是个坏主意。

RedGate Ants Memory Profiler

SciTech .NET内存分析器

EQATEC .NET分析器

CLR Profiler (Free)

因此,正如@Jalf所说,没有证据表明存在内存"泄漏":您所讨论的更接近于由垃圾收集引起的延迟。

其他人可能不同意,但我建议每秒超过几百个回调的任何东西都将扩展像c#这样的通用语言,特别是代表您管理内存的语言。所以你必须聪明地分配内存,给运行时一些帮助。

首先,得到一个真正的分析器。Perfmon有它的用途,但是即使是Visual Studio的后续版本中的分析器也可以给你提供更多的信息。我最喜欢的是sciitech分析器(http://memprofiler.com/);还有其他的,包括RedGate的一个很受尊敬的网站:http://devlicio.us/blogs/scott_seely/archive/2009/08/23/review-of-ants-memory-profiler.aspx

一旦你知道你的基线,的目标是消除gen2收集。他们会是行动迟缓的人。在任何紧循环中努力消除尽可能多的内存分配——字符串是常见的违法者。

一些有用的技巧在一篇老的但仍然相关的MSDN文章中:http://msdn.microsoft.com/en-us/library/ms973837.aspx。

阅读Tess Ferrandez关于调试ASP的(杰出的)博客系列也是很好的。. NET应用程序-预订一天离开办公室,从这里开始:http://blogs.msdn.com/b/tess/archive/2008/02/04/net-debugging-demos-information-and-setup-instructions.aspx。

我记得前一段时间读过一篇关于。net内存性能的博文(特别是XNA在XBox 360上)(不幸的是我再也找不到那个链接了)。

实现低延迟内存性能的核心是确保您永远不会在性能关键时刻运行第2代GC(尽管在延迟不重要时运行它们是可以的;在最新版本的框架中,GC类上有一堆通知回调函数,这可能会有所帮助)。有两种方法可以确保发生这种情况:

  1. 不要分配任何转义到第2代的。当你没有意识到这一点时,对象很容易逃到第2代,所以这通常转化为:不要在性能关键代码中分配任何东西。因为没有对象逃到第2代,所以GC不需要收集。
  2. 预先分配你需要的一切,使用对象池。你的第2代堆会很大,但因为没有添加任何东西,所以GC不需要收集它。
查看一些与XNA或Silverlight相关的性能文章可能会有所帮助,因为游戏和资源受限的设备通常对延迟非常敏感。(注意,这很容易,因为XBox 360和Windows Phone只有单代GC(标记和清除收集器))