2011-11-09 29 views
2

我对一个多线程应用程序使用C#2.0,该应用程序每秒从非托管dll接收至少千次回调,并定期将消息从套接字发送出去。 GUI仍然在主线程上。C#内存泄漏第0代和第1代在perfmon中不断增加 - 这是什么意思?

我的应用程序大多是在启动时创建对象,并定期执行的短暂期间。

我遇到的问题是周期性的延迟尖峰(用时间来测定冲压在开始和结束的功能),我想发生GC运行时。

我跑perfmon的,这里是我的意见......

GEN0堆大小为平与定期秒杀每隔几秒钟秒杀。

Gen1堆大小始终在卷上。向上和向下

Gen2堆大小遵循周期。它不断增加,直到它变得平坦一段时间然后下降。

Gen 0和1集合总是增加1到5个单位的范围。第2代集合是不变的。

+2

这与内存泄漏有什么关系?你只是对GC的工作方式进行一些测量,并询问为什么它的行为是一个很好的,合理的问题。但不要认为这是内存泄漏。 – jalf

回答

1

我建议使用内存分析器才能知道,如果你有一个真正的内存泄漏与否。有很多可用的,他们可以让你快速隔离任何问题。

垃圾收集器具有适应性,可以修改多久它响应您的应用程序使用内存的方式运行。仅仅看一代堆的大小,就隔离任何问题的根源而言,会告诉你很少。其次是如何运作是一个坏主意。

RedGate Ants Memory Profiler

SciTech .NET Memory Profiler

EQATEC .NET Profiler

CLR Profiler (Free)

0

那么作为@Jalf说,没有一个内存 “泄漏” 这样的证据:你们讨论什么是接近延迟造成的通过垃圾收集。

其他人可能不同意,但我建议你上面每秒几百回调东西是要伸展通用语言如C#,尤其是管理代表你​​的记忆。所以你将不得不使用你的内存分配,并给运行时间一些帮助。

首先,得到一个真正的探查。 Perfmon有其用处,但即使是更高版本的Visual Studio中的分析器也可以为您提供更多信息。我喜欢SciTech profiler best(http://memprofiler.com/);也有其他包括备受尊敬的一个从展鹏审查这里: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

0

我记得前一段时间(不幸的是我找不到上述链接)阅读关于.NET内存性能的博客文章(特别是XBox 360上的XNA)。

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

  1. 不要分配任何逃逸到根2.这是令人担忧的容易对象逃脱的Gen 2,当你没有意识到这一点,所以这往往转化为:不要在性能严重的代码中分配任何内容。因为没有对象转到第2代,GC不需要收集。
  2. 分配您需要的所有内容,并且使用对象池分配。你的第2代堆将很大,但由于没有任何东西被添加到它,GC不需要收集它。

它可能有助于寻找到一些XNA或Silverlight相关性能的文章,因为 游戏和资源受限的设备往往是非常延迟敏感。 (请注意,由于XBox 360以及Mango,Windows Phone只有一代GC(标记和清除采集器)),所以很容易。

+0

有没有办法找到哪部分代码导致第2代内存溢出?以及如何预防它? – bsobaid

+0

@bsobaid - 你需要找到你分配内存的位置。使用其他答案中提到的内存分析器将有助于确定第2代堆中的类型,由您决定分配它们的位置。显而易见的事情包括:新的类对象,字符串连接和任何LINQ。要对延迟关键代码非常严格,所有可以使用的都是:基元,基元数组和对象池。 – ligos