如何在.NET应用程序中探索托管堆以识别可能的内存优化?

Dow*_*God 10 .net heap optimization managed

我们有一个.NET应用程序,我们的客户认为它太大而无法进行大规模部署,我们希望了解是什么有助于我们的内存占用,并且可以在不完全放弃.NET和wpf的情况下做得更好.

我们有兴趣改进总大小和私人工作集(pws).在这个问题中我只想看看pws.VMMap通常会报告105 MB的pws.其中11mb是图像,31mb是堆,52mb是托管堆,7mb是私有数据,其余是堆栈,页表等.

这里最大的奖项是托管堆.我们可以直接在我们自己的代码中占用大约8mb的manged堆,即我们创建和管理的对象和窗口.其余的是由我们使用的框架元素创建的可能的.NET对象.

我们想要做的是确定框架帐户的哪个元素占这个用途的哪个部分,并且可能重新构建我们的系统以避免在可能的情况下使用它们.任何人都可以建议如何进行这项调查?

进一步澄清:

到目前为止,我已经使用了许多工具,包括优秀的ANTS分析器和带有SOS的WinDbg,它们允许我看到托管堆中的对象,但真正感兴趣的不是"什么?",而是"为什么? " 理想情况下,我希望能够说,"好吧,因为我们使用WCF,所以在这里创建了10mb的对象.如果我们编写自己的本地传输,我们可以节省8mb的x质量风险和开发工作."

不可能在300,000多个对象上执行gcroot.

Sim*_*ens 10

WinDbg可能是一个有用的工具.它随Windows调试工具一起提供.

应用程序运行后,您可以附加WinDbg并浏览托管堆.(或者您可以进行内存转储并离线浏览).它将能够非常快速地告诉您消耗最大内存量的对象类型.

首先,您需要加载SOS扩展,以便调试托管应用程序:

.loadby sos mscorwks
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用!dumpheap获取堆信息,-stat交换机提供有关分配类型的整体堆信息:

!dumpheap -stat
Run Code Online (Sandbox Code Playgroud)

-type参数提供有关指定类型的已分配实例的特定信息:

!dumpheap -type System.String
Run Code Online (Sandbox Code Playgroud)

您可能会发现许多其他命令,例如:

  • !gcroot - 跟随一个已分配的对象备份它的root来查找它在内存中的原因.
  • !dumpobj - 转储特定对象,以便您可以看到它的内容.
  • !EEHeap - 给出一些一般的堆统计信息.

MSDN具有SOS命令及其开关的完整列表.

WinDbg是一个非常复杂的工具,但如果您搜索以帮助您入门,那么在线有很多教程和指南.或者,我可以推荐John Robbins编写的" 调试Microsoft .NET 2.0应用程序 "一书,该书详细介绍了WinDbg和SOS的.net调试功能.

您可以将SOS扩展加载到visual studio中,而不是将其输入到即时窗口中,然后您应该能够直接在VS立即窗口中使用SOS命令:

.load SOS.dll
Run Code Online (Sandbox Code Playgroud)

您也可以找到CLR Profiler和本使用指南.

  • !gcroot和!dumpobj的组合通常可以帮我完成工作.如果您的所有代码都在一个公共名称空间中,那么您不能只执行类似!dumpheap -stat -type YourCompaniesNamespace.这将为您提供代码中最大的内存使用类,您可以看到是否有值得挑选的东西.你从WinDbg获得的所有内容都是线索,你必须跳回到代码中,将这些线索与一些实际行为联系起来. (2认同)