2010-03-24 82 views
2

我知道有没有简单的回答我的问题,但我会很感激的想法,指南或 某种东西到查找在列表OutOfMemoryException异常 - 出出主意

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

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

我的应用程序有线程和锁定对象,DB连接和WCF接口。 的一般问题,我试图解决:

根本就没有得到它GC足够快 到GC对象或一些非管理 (窗口)对象正在消耗 内存?

见列表 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

+0

在我看来,你有一些对象不是释放(内存泄漏),或者你的CPU工作太多,框架决定不运行垃圾回收器。还可以查看MSDN垃圾收集器的延迟模式 - http://msdn.microsoft.com/zh-cn/library/bb384202.aspx。你到目前为止使用了哪种内存分析器? – 2010-03-24 12:21:42

+0

你是从数据库中查询很多数据吗? – AndrewC 2010-03-24 12:26:42

+0

嗨Mikael,我试过dotTrace和蚂蚁。他们也崩溃(有时) 将看看你提供的链接。 – 2010-03-24 12:31:39

回答

7

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

苔丝费兰德斯有很多优秀的演示。 She goes through the most useful stuff here...

3

我用.Net Memory Profiler它比微软的clr profiler好得多。你必须稍微了解一下。它可以告诉你哪个对象没有处理或有参考。你也可以根据类型和内存对对象进行排序。我使用了最近30天的试用版,在此期间我能够在我的应用程序中解决问题。

4

你的问题很可能是经典的泄漏(当它们不应该是根源的时候)或大对象堆(LOH)碎片。

我发现诊断此类问题的最佳工具是Windows调试器的Strike(SOS)扩展。下载微软的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. 应用程序是否具有订阅具有长寿命对象的事件的临时对象?

(我之所以问这是1. .NET串实习生表是在这样一种方式,它们能引起LOH fragmenation和2事件订阅提供了额外的根订阅对象,它是实现容易忘记。)

+0

嗨Paul,CDB或WinDbg可以附加到运行进程吗? – 2010-03-24 12:53:29

+0

是的,运行'CDB -pv -p 1234',其中1234是进程ID。 – 2010-03-24 12:54:57

+0

(另外,'q'退出调试器并解冻你的过程。) – 2010-03-24 12:55:31

1

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

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

希望这会有所帮助。