C# OutOfMemoryException-OutofIdeas

C# OutOfMemoryException-OutofIdeas,c#,.net,profiling,out-of-memory,C#,.net,Profiling,Out Of Memory,我知道我的问题没有简单的答案,但我希望有一些想法、指导或建议 一些要看清单的东西 我有一个NetWindows服务,它不断抛出OutOfMemoryException。 该服务有两个用于x86和x64 Windows的版本。然而,在x64上,它消耗更多 记忆。我尝试过用各种内存分析器分析它。但我不知道问题出在哪里。诊断服务消耗大量VMSize,并在3到12小时后使应用程序崩溃。行为是相当随机的-没有可观察到的模式为崩溃的情况 我还尝试查看性能计数器(perfmon.exe)。我能看到的是 堆大小

我知道我的问题没有简单的答案,但我希望有一些想法、指导或建议 一些要看清单的东西

我有一个NetWindows服务,它不断抛出OutOfMemoryException。 该服务有两个用于x86和x64 Windows的版本。然而,在x64上,它消耗更多 记忆。我尝试过用各种内存分析器分析它。但我不知道问题出在哪里。诊断服务消耗大量VMSize,并在3到12小时后使应用程序崩溃。行为是相当随机的-没有可观察到的模式为崩溃的情况

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

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

难道这还不够快吗 到GC对象或某些非托管对象 (windows)对象正在使用 记忆

查看列表中的第一个应用程序

指向带有性能计数器视图的图片的链接

您不知道是什么消耗了大量内存?当进程占用大量内存时,您可以打开任务管理器,右键单击进程并创建一个转储文件,您可以在windbg中查看该文件,以了解到底是什么在分配内存


Tess Ferrandez有很多优秀的演示

我使用它比微软的clr分析器要好得多。你必须了解一点。它可以告诉您哪些对象没有处理或没有引用。您还可以根据对象的类型和内存对对象进行排序。我使用了试用版,它持续了30天,在此期间我能够解决我的应用程序中的问题。

您的问题可能是典型的泄漏(对象在不应该的时候仍处于根状态)或大对象堆(LOH)碎片

我找到的诊断这类问题的最佳工具是Windows调试器的SOS扩展。下载微软的调试器: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) 0:000>.loadby sos mscorwks 0:000> !EEHeap-gc GC堆的数量:1 第0代从0x00f7a9b0开始 第1代从0x00e79c3c开始 第2代从0x00b21000开始 临时段分配上下文:无 段开始分配大小 00b20000 00b21000 010029bc 0x004e19bc(5118396) 大型对象堆从0x01b21000开始 段开始分配大小 01b20000 01b21000 01b8ade0 0x00069de0(433632) 如果有很多LOH片段,那么我开始怀疑LOH片段

然而,在此之前,我想知道:

  • 应用程序是否使用string.Intern()
  • 应用程序是否具有订阅具有长寿命对象的事件的瞬态对象

  • (我问这个问题的原因是1.NET字符串intern表的实现方式可能导致LOH碎片化,2.事件订阅为订阅对象提供了一个很容易忘记的附加根。)

    如果您花费在GC上的时间百分比很高,那么我会查看LOH分配性能计数器。如果LOH中有频繁的分配,这将导致GC努力收集,这也是GC花费大量时间的原因

    我写了一篇博客,介绍了如何获得LOH中分配的确切调用堆栈


    希望这有帮助

    在我看来,您有一些未释放的对象(内存泄漏),或者您的CPU工作过度,以至于框架决定不运行垃圾收集器。还可以在MSDN-上查看垃圾收集器的延迟模式。到目前为止,您使用了哪种内存探查器?您是否从数据库中查询了大量数据?使用内存探查器时,您不需要等待内存不足错误,就像您可以在泄漏失控之前看到它的累积一样。在这种情况下,探查器不应崩溃。@Captain Comic:如果您想排除由于处理器繁忙而导致GC未运行的可能性,请在关键位置或计时器中输入GC.Collect(),以强制收集。如果内存仍在增加,则表示您有未释放的对象。发生了未处理的异常OutOfIdeasException…嗨,Paul,CDB或WinDbg可以附加到正在运行的进程吗?是的,运行“CDB-pv-p 1234”,其中1234是进程ID。(另外,“q”退出调试器并解冻进程。)