我有一个.NET服务,其正常的私有工作集大约为80 MB。在最近的负载测试期间,进程达到3.5 GB内存使用率,导致整个机器的物理内存不足(使用4 GB中的3.9),并且在负载测试停止后很长时间内内存未释放。使用任务管理器,我获取了该进程的转储文件并在Visual Studio 2010 SP1中打开它,我可以开始调试它。
如何诊断内存问题?我有dotTrace Memory 3.x,它是否支持转储文件的内存分析?如果没有,Visual Studio 2010 Premium的内存分析功能是否有帮助(我目前有专业版)? WinDbg能帮忙吗?
更新:新的 Visual Studio 2013 Ultimate 现在可以使用转储文件本机诊断内存问题。有关详细信息,请参阅this blog post。
答案 0 :(得分:120)
安装WinDbg。您需要确保获得正确的x86或x64版本,具体取决于您的转储。以下是x86 download的直接链接。
在此,你需要确保你采取了正确的转储。您可以使用任务管理器创建转储文件(右键单击进程 - >创建转储文件)。 如果您使用64位且进程为x86,请使用32位版本的任务管理器(C:\ Windows \ SysWOW64 \ taskmgr.exe)来获取转储文件。有关获取转储文件的更多信息,请参阅my article,例如,如果您使用的是XP并且需要使用windbg来创建转储文件。
警告有一个相当陡峭的学习曲线,事情可能无法完全按照此处所述进行操作,所以回过头来解决任何问题。
我假设您正在使用.NET4,因为您可以在Visual Studio中打开转储。这是一个非常快速指南,可帮助您使用dmp文件:
1)运行WinDbg,将符号路径(文件 - >符号搜索路径)设置为
SRV*c:\symbols*http://msdl.microsoft.com/download/symbols
2)打开崩溃转储或将.DMP文件拖到WinDbg上。
3)在命令窗口中输入
.loadby sos clr
(仅供参考,对于.NET 2,命令应为.loadby sos mscorwks
)
4)然后输入
!dumpheap -stat
列出了对象的类型及其计数。 看起来像这样:
您必须在应用程序的上下文中分析这一点,看看是否有任何异常。
windbg还有很多,谷歌是你的朋友。
答案 1 :(得分:28)
通常,如果托管应用程序中存在泄漏,则表示未收集任何内容。常见来源包括
事件处理程序:如果订阅者未被删除,发布者将保留该订阅者。
静
终结器:阻塞的终结器将阻止终结器线程运行任何其他终结器,从而防止收集这些实例。
类似地,死锁线程将保留它所拥有的任何根。当然,如果你有死锁的线程,可能会影响几个级别的应用程序。
要解决此问题,您需要检查托管堆。 WinDbg + SOS(或PSSCOR)将允许您这样做。 !dumpheap -stat
命令列出整个托管堆。
您需要了解堆上预期的每种类型的实例数。一旦找到奇怪的东西,就可以使用!dumpheap -mt <METHOD TABLE>
命令列出给定类型的所有实例。
下一步是分析这些实例的根。随机选择一个并对其进行!gcroot
。这将显示该特定实例是如何生根的。查找事件处理程序和固定对象(通常表示静态引用)。如果你在那里看到终结器队列,你需要检查终结器线程正在做什么。使用!threads
和!clrstack
命令。
如果该实例的一切看起来都很好,那么您将转到另一个实例。如果这不会产生任何结果,您可能需要再次回头查看堆并从那里重复。
其他泄漏源包括:未卸载的程序集和大对象堆的碎片。 SOS / PSSCOR也可以帮助您找到这些,但我现在将跳过详细信息。
如果您想了解更多,我建议Tess' blog。我还做了一些关于如何使用WinDbg + SOS(here和here)的视频。
如果您可以选择在运行过程中调试该过程,我建议使用PSSCOR而不是SOS。 PSSCOR本质上是SOS源的私有分支,已经通过附加命令进行了增强,并且许多现有的SOS命令也得到了改进。例如。 !dumpheap
命令的PSSCOR版本具有非常有用的增量列,这使得对内存泄漏的故障排除变得更加容易。
要使用它,您需要启动流程,附加WinDbg并加载PSSCOR并执行!dumpheap -stat
。然后让流程再次运行,以便进行分配。中断执行并重复命令。现在,PSSCOR将显示自上次检查以来添加/删除的实例数。
答案 2 :(得分:4)
自版本2017.2以来,JetBrains dotMemory支持Windows内存转储分析及其所有功能和精美的GUI。
答案 3 :(得分:0)
http://msdn.microsoft.com/en-us/library/ee817660.aspx
微软在这里有一个指南。然而,这对初学者来说太难了。
dotTrace可以生成可视内存图表(优于WinDbg),但绝不会将其用于转储。