OutOfMemoryException - 出于想法

时间:2010-03-24 12:15:50

标签: c# .net profiling out-of-memory

我知道我的问题没有简单的答案,但我会很感激想法,指南或者 某种事情看待清单

我有一个不断抛出OutOfMemoryException的网络Windows服务。 该服务有两个用于x86和x64 Windows的版本。但是在x64上它会消耗更多 记忆。我尝试使用各种内存分析器对其进行分析。但我无法弄清楚问题是什么。诊断 - 服务消耗了大量的VMSize并在3到12小时后崩溃应用程序。行为是相当随机的 - 崩溃情景没有可观察的模式。

另外,我试着看一下性能计数器(perfmon.exe)。我能看到的是 堆大小正在增长,%GC时间平均为19%。内存分配与%CPU时间相关。

我的应用程序有线程和锁定对象,数据库连接和WCF接口。 我想解决的一般性问题:

  

仅仅GC还不够快   到GC对象或一些非托管   (windows)对象正在消耗   存储器?

查看列表中的第一个应用 http://s45.radikal.ru/i109/1003/af/92a389d189e8.jpg http://s45.radikal.ru/i109/1003/af/92a389d189e8.jpg

带有性能计数器视图的图片链接 http://s006.radikal.ru/i215/1003/0b/ddb3d6c80809.jpg

4 个答案:

答案 0 :(得分:7)

你的问题是你不知道消耗大量内存的是什么?当进程使用大量内存时,您可以打开任务管理器,右键单击您的进程并创建一个转储文件,您可以在windbg中检查该文件以确切了解分配内存的内容。

Tess Ferrandez有很多优秀的演示。 She goes through the most useful stuff here...

答案 1 :(得分:4)

您的问题很可能是经典泄漏(当它们不应该存在时仍然生根的对象)或大对象堆(LOH)碎片。

我发现用于诊断此类问题的最佳工具是Windows调试器的Son of Strike(SOS)扩展。下载Microsoft的Debugging Tools for Windows以获取调试器:CDB是控制台调试器(我更喜欢它,因为它似乎响应更快),WinDbg与MDI应用程序包装相同。这些工具水平较低,有一些学习曲线,但提供了解决问题所需的一切。

特别是,运行!DumpHeap -stat以查看哪些类型的对象正在占用您的记忆。如果注意到任何重大碎片,此命令也将在列表底部报告。 !EEHeap将列出堆段 - 如果有很多LOH段,那么我会怀疑LOH碎片。

0:000> .loadby sos mscorwks
0:000> !EEHeap -gc
Number of GC Heaps: 1
generation 0 starts at 0x00f7a9b0
generation 1 starts at 0x00e79c3c
generation 2 starts at 0x00b21000
ephemeral segment allocation context: none
 segment    begin allocated     size
00b20000 00b21000  010029bc 0x004e19bc(5118396)
Large object heap starts at 0x01b21000
 segment    begin allocated     size
01b20000 01b21000  01b8ade0 0x00069de0(433632)         

如果有很多LOH段,那么我会开始怀疑LOH碎片。

然而,在此之前,我有兴趣知道:

  1. 应用程序是否使用string.Intern()?
  2. 应用程序是否具有订阅具有长期对象的事件的临时对象?
  3. (我之所以这样说是因为1. .NET字符串实习表的实现方式可能会导致LOH碎片化,而事件订阅会为订阅对象提供额外的根,这很容易被遗忘。)

答案 2 :(得分:3)

我使用.Net Memory Profiler比使用microsoft的clr profiler好得多。你必须要了解一点。它可以告诉您哪个对象没有处理或有引用。您还可以根据类型和内存对对象进行排序。我使用了最近30天的试用版,在此期间我能够在我的申请中解决问题。

答案 3 :(得分:1)

如果您在GC上花费的百分比时间很长,那么我会看看LOH Allocations perfmon counter。如果在LOH中频繁分配,这将导致GC努力收集,这是GC花费高百分比时间的原因。

我做了关于identifying high CPU in GC because of LOH的博客,其中显示了如何获得在LOH中分配的确切调用堆栈。

希望这会有所帮助。