C#内存泄漏?第0代和第1代在perfmon中不断增加 - 这是什么意思?

时间:2011-11-09 19:12:21

标签: c# garbage-collection perfmon

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

我的应用程序主要在启动时创建对象,并在执行期间定期创建一小段时间。

我遇到的问题是周期性延迟峰值(通过在开始和结束时对函数加时间戳来衡量),我猜想在GC运行时会发生这种情况。

我跑了perfmon,这是我的观察......

Gen0堆大小是平坦的,每隔几秒就有一个尖峰,周期性尖峰。

Gen1堆大小始终在滚动。上下

Gen2堆大小遵循一个循环。它会持续增加,直到它变平一段时间然后下降。

Gen 0和1集合总是在1到5个单位的范围内增加。 Gen 2系列不变。

3 个答案:

答案 0 :(得分:1)

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

垃圾收集器是自适应的,它将修改它运行的频率,以响应应用程序使用内存的方式。只看一代堆大小就会在隔离任何问题的根源方面告诉你很少。第二次询问它是如何工作的是一个坏主意。

RedGate Ants Memory Profiler

SciTech .NET Memory Profiler

EQATEC .NET Profiler

CLR Profiler (Free)

答案 1 :(得分:0)

正如@Jalf所说,没有证据表明内存存在“泄漏”:你所讨论的内容更接近垃圾收集造成的延迟。

其他人可能不同意,但我建议每秒几百回调以上的任何东西都会扩展像C#这样的通用语言,特别是代表你管理内存的语言。因此,您将不得不熟悉内存分配并为运行时提供一些帮助。

首先,获得一个真实的探查者。 Perfmon有其用途,但即使是Visual Studio的更高版本中的分析器也可以为您提供更多的更多信息。我最喜欢SciTech探测器(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

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

答案 2 :(得分:0)

我记得刚才读过一篇关于.NET内存性能的博客文章(特别是XBox 360上的XNA)(遗憾的是我再也找不到这个链接了)。

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

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