75

我有一个 .NET 服务,其正常的私有工作集约为 80 MB。在最近的一次负载测试中,进程达到了 3.5 GB 内存使用量,导致整机物理内存不足(使用了 4 GB 中的 3.9 个),并且在负载测试停止后很长时间没有释放内存。使用任务管理器,我获取了进程的转储文件并在 Visual Studio 2010 SP1 中打开它,我可以开始对其进行调试。

如何诊断内存问题?我可以使用 dotTrace Memory 3.x,它是否支持对转储文件进行内存分析?如果没有,Visual Studio 2010 Premium 的内存分析功能会有所帮助吗(我目前有 Professional)?WinDbg 可以提供帮助吗?

更新:新的Visual Studio 2013 Ultimate现在可以使用转储文件本地诊断内存问题。有关更多详细信息,请参阅此博客文章

4

4 回答 4

128

安装 WinDbg。您需要确保根据您的转储获得正确的 x86 或 x64 版本。这是x86下载的直接链接。

在这方面,您需要确保您进行了正确的转储。您可以使用任务管理器创建转储文件(右键单击进程 -> 创建转储文件)。如果您使用的是 64 位并且您的进程是 x86,请使用 32 位版本的任务管理器 (C:\Windows\SysWOW64\taskmgr.exe) 来获取转储文件。有关获取转储文件的更多信息,请参阅我的文章,例如,如果您使用的是 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还有很多,谷歌是你的朋友。

于 2012-03-01T15:09:10.067 回答
33

通常,如果托管应用程序中有泄漏,则意味着没有收集到某些东西。常见来源包括

  • 事件处理程序:如果订阅者未删除,则发布者将保留它。

  • 静力学

  • 终结器:阻塞的终结器将阻止终结器线程运行任何其他终结器,从而阻止收集这些实例。

  • 类似地,死锁线程将保留它所持有的任何根。当然,如果您有可能会在多个级别上影响应用程序的死锁线程。

要解决此问题,您需要检查托管堆。WinDbg + SOS(或 PSSCOR)会让你这样做。该!dumpheap -stat命令列出整个托管堆。

您需要了解堆上预期的每种类型的实例数。一旦你发现一些看起来很奇怪的东西,你可以使用该!dumpheap -mt <METHOD TABLE>命令列出给定类型的所有实例。

下一步是分析这些实例的根源。随机选择一个并!gcroot对其进行操作。这将显示该特定实例是如何植根的。寻找事件处理程序和固定对象(通常表示静态引用)。如果您在那里看到终结器队列,则需要检查终结器线程在做什么。为此使用!threadsand!clrstack命令。

如果该实例的一切看起来都很好,那么您将转到另一个实例。如果这没有产生任何结果,您可能需要返回再次查看堆并从那里重复。

其他泄漏源包括: 未卸载的程序集和大对象堆的碎片。SOS/PSSCOR 也可以帮助您找到这些,但我现在将跳过详细信息。

如果你想了解更多,我推荐Tess 的博客。我还制作了几个视频,介绍如何使用 WinDbg + SOS(此处此处)。

如果您可以选择在进程运行时对其进行调试,我建议您使用PSSCOR而不是 SOS。PSSCOR 本质上是 SOS 源的一个私有分支,已通过附加命令进行了增强,并且许多现有的 SOS 命令也得到了改进。例如,该命令的 PSSCOR 版本!dumpheap有一个非常有用的 delta 列,这使得解决内存泄漏问题变得更加容易。

为了使用它,您需要启动您的进程,附加 WinDbg 并加载 PSSCOR 并执行!dumpheap -stat. 然后让进程再次运行,以便进行分配。中断执行并重复命令。现在 PSSCOR 将显示自上次检查以来添加/删除的实例数。

于 2012-03-01T16:12:41.517 回答
6

自 2017.2 版以来,JetBrains dotMemory 以其强大的功能和精美的 GUI 支持 Windows 内存转储分析。

于 2017-12-04T19:06:22.273 回答
0

http://msdn.microsoft.com/en-us/library/ee817660.aspx

微软在这里有一个指南。但是,对于初学者来说太难了。

dotTrace 可以生成可视化内存图表(比 WinDbg 更好),但从不将其用于转储。

于 2012-03-01T12:26:20.550 回答