C# 内存泄漏?第 0 代和第 1 代的 perfmon 不断增加 - 这是什么意思?
我正在将 C# 2.0 用于多线程应用程序,该应用程序每秒从非托管 dll 接收至少一千个回调,并定期从套接字发送消息。 GUI 保留在主线程上。
我的应用程序主要在启动时创建对象,并在短暂的执行期间定期创建对象。
我遇到的问题是周期性的延迟峰值(通过在开始和结束时对函数进行时间戳测量),我认为这是在 GC 运行时发生的。
我运行了 perfmon,这是我的观察结果...
Gen0 堆大小是平坦的,每隔几秒就会出现一个峰值,并且会出现周期性峰值。
Gen1 堆大小始终在滚动中。 Gen2 堆大小的上下变化
遵循一个循环。它不断增加,直到一段时间变得平坦,然后下降。
第 0 代和第 1 代系列始终以 1 到 5 个单位的范围增加。 第 2 代系列是恒定的。
I am using C# 2.0 for a multi-threaded application that receives atleast thousand callbacks per second from an unmanaged dll and periodically send messages out of socket. GUI remains on main thread.
My application mostly creates object at the startup and periodically during the execution for a short lived period.
The problem I am experiencing is periodic latency spike (measured by time stamping a function at start and end) which I suppose happen when GC run.
I ran perfmon and here are my observations...
Gen0 Heap Size is flat with a spike every few seconds with periodic spike.
Gen1 Heap Size is always on the roll. Up and down
Gen2 Heap Size follows a cycle. It keep increasing till it becomes flat for a while and then drops.
Gen 0 and 1 Collections are always increasing in a range of 1 to 5 units.
Gen 2 collections is constant.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我建议使用内存分析器来了解是否存在真正的内存泄漏。有很多可用的方法,它们可以让您快速隔离任何问题。
垃圾收集器是自适应的,将根据应用程序使用内存的方式修改其运行频率。仅仅查看生成堆大小对于隔离任何问题的根源来说并不能告诉您什么。再次询问它是如何工作的不是一个好主意。
RedGate Ants 内存分析器
SciTech .NET 内存分析器
EQATEC .NET 探查器
CLR 探查器(免费)< /a>
I recommend using a memory profiler in order to know if you have a real memory leak or not. There are many available and they will allow you to quickly isolate any issue.
The garbage collector is adaptive and will modify how often it runs in response to the way your application is using memory. Just looking at the generation heap sizes is going to tell you very little in terms of isolating the source of any problem. Second quessing how it works is a bad idea.
RedGate Ants Memory Profiler
SciTech .NET Memory Profiler
EQATEC .NET Profiler
CLR Profiler (Free)
因此,正如 @Jalf 所说,没有证据表明存在内存“泄漏”:您讨论的更接近于垃圾收集引起的延迟。
其他人可能不同意,但我建议每秒数百次回调以上的任何内容都会扩展像 C# 这样的通用语言,尤其是代表您管理内存的语言。因此,您必须巧妙地分配内存并为运行时提供一些帮助。
首先,获得一个真正的分析器。 Perfmon 有其用途,但即使是 Visual Studio 更高版本中的探查器也可以为您提供更多信息。我最喜欢 SciTech profiler (http://memprofiler.com/);还有其他一些,包括来自 RedGate 的备受尊敬的评论:http://devlicio.us/blogs/scott_seely/archive/2009/08/23/review-of-ants-memory-profiler.aspx
一旦您了解了自己的基线,旨在消除第二代收藏。他们将是真正缓慢的人。在任何紧密的循环中努力消除尽可能多的内存分配——字符串是最常见的问题。
一些有用的提示位于一篇旧的但仍然相关的 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。
So as @Jalf says, there's no evidence of a memory "leak" as such: what you discuss is closer to latency caused by garbage collection.
Others may disagree but I'd suggest anything above a few hundred callbacks per second is going to stretch a general purpose language like C#, especially one that manages memory on your behalf. So you're going to have to get smart with your memory allocation and give the runtime some help.
First, get a real profiler. Perfmon has its uses but even the profiler in later versions of Visual Studio can give you much more information. I like the SciTech profiler best (http://memprofiler.com/); there are others including a well respected one from RedGate reviewed here: http://devlicio.us/blogs/scott_seely/archive/2009/08/23/review-of-ants-memory-profiler.aspx
Once you know your baseline, aim to eliminate gen2 collections. They'll be the really slow ones. Work hard in any tight loops to eliminate as much memory allocation as you can -- strings are the usual offenders.
Some useful tips are in an old but still relevant MSDN article here: http://msdn.microsoft.com/en-us/library/ms973837.aspx.
It's also good to read Tess Ferrandez's (outstanding) blog series on debugging ASP.NET applications - book a day out of the office and start here: http://blogs.msdn.com/b/tess/archive/2008/02/04/net-debugging-demos-information-and-setup-instructions.aspx.
我记得不久前读过一篇关于 .NET 内存性能的博客文章(特别是 XBox 360 上的 XNA)(不幸的是我再也找不到所述链接了)。
实现低延迟内存性能的简而言之就是确保您永远不会在性能关键时刻运行第 2 代 GC(尽管在延迟不重要时运行它们是可以的;
GC
类这可能会有所帮助)。有两种方法可以确保发生这种情况:查看一些 XNA 或 Silverlight 相关的性能文章可能会有所帮助,因为
游戏和资源受限的设备通常对延迟非常敏感。 (请注意,这很容易,因为 Xbox 360 以及 Mango 之前的 Windows Phone 仅具有单代 GC(标记和清除收集器))。
I remember reading a blog post about memory performance in .NET (specifically, XNA on the XBox 360) a while ago (unfortunately I can't find said link anymore).
The nutshell of achieving low latency memory performance was to make sure you never run gen 2 GC's at a performance critical time (although it is OK to run them when latency is not important; there are a bunch of notification callback functions on the
GC
class in more recent versions of the framework which may help with this). There are two ways to make sure this happens:It may be helpful to look into some XNA or Silverlight related performance articles because
games and resource constrained devices are often very latency sensitive. (Note that you have it easy because the XBox 360 and, until Mango, Windows Phone only had a single generation GC (mark-and-sweep collector)).