我在.net中有一个应用程序,它可以获得越来越多的内存。 我从团队成员那里得到了一些关于我的应用程序分配的最常见和最重的实例的分析。
问题在于我不知道接下来该做什么。 源代码很大!! 我需要最好地练习如何捕获有问题的函数/代码行。
p.s - 我尝试过使用visual studio的“.net内存分配(采样)”功能,但总是无法创建报告。 (猜测可能是另一个问题)。
答案 0 :(得分:1)
Visual Studio Profiler
完全符合您的要求,能够在调用堆栈中显示热路径。您将学习如何使用分析器,因此如果您无法生成Visual Studio分析器报告并且无法调查如何执行此操作 - 首先需要开始阅读文档,因为无论您在这种情况下使用哪种工具。
以下是有关Visual Studio探查器的有用链接:
编辑:VS Profiler的热门路径:
答案 1 :(得分:0)
我首先要做的一件简单的事情就是使用windbg和psscor2。 然后我做了一个!gcroot和/或!GCRef。此有时可让您深入了解保持对象存活的基本引用。
对于那个匆忙的回答感到抱歉,如果您不了解psscor2,请查看示例this blog以获取更多参考资料
答案 2 :(得分:0)
如果我没弄错的话,你的队友似乎已经在使用带有托管扩展的WinDbg(也许是SOS?)并且已经调用!dumpheap -stat 。获取他的内存转储文件的副本,在WinDbg中打开它,然后加载SOS。
第一步是深入研究特定类型。在你的情况下,看起来你有一个非常大的字符串分配(大约84MB)。因此,请尝试运行:
查看字符串列表!dumpheap -type System.String
它将输出长字符串实例列表。输出看起来像这样:
Address MT Size Gen
0x412d0030 0x79b94638 812 1 System.String XXXX
0x422d0030 0x79b94638 812 1 System.String XXXX
0x432d0030 0x79b94638 812 1 System.String XXXX
这个命令可能会运行几分钟,因为你有很多字符串实例但是在运行时会尝试观察输出。如果您注意到许多实例具有相同的大小,那通常表明您没有正确释放资源。任何这些实例都是下一步的良好候选者。如果在列表的末尾你也看到了大尺寸的字符串,这些也是下一步的好选择。
下一步是检查哪些对象引用了特定的字符串实例,并防止它被垃圾回收。您可以使用上面 dumpheap 输出中的地址,然后调用:
!gcroot 0x432d0030
这将输出如下内容:
173866dc(System.Web.UI.WebControls.ListItemCollection)->
173866ec(System.Collections.ArrayList)->
173894b8(System.Object[])->
17386d0c(System.Web.UI.WebControls.ListItem)->
17386ce8(System.String)
您可以从下到上阅读。因此,在此示例中, String 由 ListItem 保存,而 ListItem 又由 Objects 数组保存。在这一点上,解决你的问题变得更加艺术化。从该链的底部开始(包括 String ),对于每一行上升,检查是否可以证明将该对象存储在内存中。如果没有,那么你应该找到一种方法来释放该资源并将其收集垃圾。此步骤很可能需要您查看和分析每个类的代码。
提示:由于System.Action的实例数量异常庞大,因此您很有可能订阅了事件/多播委托,之后忘记取消订阅。