如何使用转储文件来诊断内存泄漏?
我有一个正常的私人工作集大约80 MB的.NET服务。 在最近的负载testing期间,进程达到了3.5 GB的内存使用量,导致整个机器在物理内存上很低(使用4 GB的3.9 GB),并且在负载testing停止后很久没有释放内存。 使用任务pipe理器,我拿了一个进程的转储文件,并在Visual Studio 2010 SP1中打开它,我可以开始debugging它。
如何诊断内存问题? 我有我的dotTrace内存3.x,它是否支持转储文件上的内存分析? 如果没有,Visual Studio 2010 Premium的内存分析function将帮助(我目前有专业人士)? WinDbg可以帮忙吗?
更新:新的Visual Studio 2013旗舰版现在可以使用转储文件本机诊断内存问题。 看到这个博客文章的更多细节。
安装WinDbg。 您需要确保您获得正确的版本x86或x64取决于您的转储。 这里是x86 下载的直接链接。
在此,你需要确保你采取了正确的转储。 您可以使用任务pipe理器来创build转储文件(右键点击进程 – >创build转储文件)。 如果您使用的是64位,而且进程是x86,则使用32位版本的任务pipe理器(C:\ Windows \ SysWOW64 \ taskmgr.exe)来获取转储文件。 请参阅我的文章获取有关转储文件的更多信息,例如,如果您在XP上,并需要使用windbg来创build转储文件。
警告有一个相当陡峭的学习曲线,事情可能无法完全按照此处所述的方式工作,所以回到任何问题。
我假设你正在使用.NET4,因为你可以在Visual Studio中打开转储。 这是一个非常快速的指南,可以帮助您处理您的dmp文件:
1)运行WinDbg,设置符号path(File – > Symbol Search Path)为
SRV*c:\symbols*http://msdl.microsoft.com/download/symbols
2)打开崩溃转储或拖动您的.DMP文件到WinDbg。
3)在命令窗口中input
.loadby sos clr
(FYI,对于.NET 2,命令应该是.loadby sos mscorwks
)
4)然后input这个
!dumpheap -stat
其中列出了对象的types和数量。 看起来像这样:
你将不得不在你的应用程序的上下文中分析,看看是否有什么exception。
windbg还有很多 ,google是你的朋友。
一般来说,如果您在托pipe应用程序中发生泄漏,则意味着某些内容未被收集。 常见的来源包括
-
事件处理程序:如果用户没有被删除,发布者将会保留它。
-
静力学
-
终结器:终止器将阻止终结器线程运行任何其他终结器,从而阻止收集这些事件。
-
同样,一个死锁的线程将保持它所拥有的任何根。 当然,如果你有死锁的线程,可能会影响在几个层面上的应用程序。
为了解决这个问题,你需要检查托pipe堆。 WinDbg + SOS(或PSSCOR)会让你这样做。 !dumpheap -stat
命令列出了整个托pipe堆。
您需要了解堆中预期的每种types的实例数量。 一旦发现看起来很奇怪的东西,可以使用!dumpheap -mt <METHOD TABLE>
命令列出给定types的所有实例。
下一步是分析这些实例的根。 随便选一个,然后做一个!gcroot
。 这将显示特定实例的根源。 寻找事件处理程序和固定对象(通常表示静态引用)。 如果你在那里看到终结器队列,你需要检查终结器线程在做什么。 使用!threads
和!clrstack
命令。
如果一切看起来都很好,那么就转到另一个实例。 如果没有产生任何东西,你可能需要回头再看堆,然后重复。
其他泄漏源包括:未卸载的组件和大对象堆的碎片。 SOS / PSSCOR可以帮助你find这些,但是现在我将跳过细节。
如果你想知道更多,我推荐苔丝的博客 。 我也做了一些video,介绍如何使用WinDbg + SOS( 这里和这里 )。
如果您可以在运行时debugging进程,则build议使用PSSCOR而不是SOS。 PSSCOR实质上是SOS资源的一个专用分支,已经增加了额外的命令,现有的许多SOS命令也得到了改进。 例如, !dumpheap
命令的PSSCOR版本有一个非常有用的增量列,这使得更容易排除内存泄漏。
为了使用它,你需要启动你的进程,附加WinDbg并加载PSSCOR并执行!dumpheap -stat
。 然后让进程再次运行,以便进行分配。 中断执行并重复该命令。 现在PSSCOR会显示自上次检查以来添加/删除的实例的数量。
http://msdn.microsoft.com/en-us/library/ee817660.aspx
微软在这里有一个指南。 不过,这对初学者来说太难了。
dotTrace可以生成可视化内存图表(比WinDbg更好),但从不用于转储。