当Gen2中存在大量对象时,使用WinDbg查找内存泄漏

本文关键字:使用 WinDbg 查找 泄漏 内存 对象 Gen2 存在 | 更新日期: 2023-09-27 18:19:52

我的.NET应用程序出现内存问题,在初始化和加载所有内容后,我的应用程序开始在Gen2堆中消耗大约1GB。随着时间的推移(4-5小时),它最终在Gen2堆中消耗4GB。我已经使用WinDbg来分析我看到的一些对象类型(以及相关的内存使用量)正在增加的事情。

在实例中增长的所有对象(以及内存使用情况)都由相同的父对象类型引用。这个父对象类型有大约3900个实例——这一点永远不会改变。不知怎的,我正在将子对象添加到这些父实例中的一些中,但我没有一个好的方法来查看3900个实例中的哪些被添加到。

DumpHeap-mt会显示我所有的父类型,但大小都是一样的,因为它不包括子类型。

ObjSize也会计算子对象的大小,但一个参数一次只取一个对象(或者所有类型的所有对象,而不仅仅是我的父类型,这太多对象了)

查看子对象并将其追溯到父对象也没有帮助,因为有几百万种这样的类型,我看不出有什么方法可以进行某种聚合跟踪。

像CLRProfiler和ANTS这样的工具使我的应用程序速度过慢(ANTS则不然),无法在任何合理的时间内解决问题。

为了使调试更容易,我曾尝试使用通常运行的一小部分数据来运行我的应用程序,但我在这里没有遇到内存问题。我认为在我的整个数据集中有一些边缘案例会引起奇怪的事情,但我不知道这些边缘案例是什么,以便将它们隔离到我整个数据集中的一个子集中。

我已经广泛阅读了这方面的内容,看不到有人建议当Gen2中有很多应该存在的对象和少量相同类型的对象不断增加时该怎么办。

任何提示都将不胜感激。

当Gen2中存在大量对象时,使用WinDbg查找内存泄漏

有趣的谜题。正如你所知,当对象在集合中幸存下来时,它们会被提升到第二代,因为它们被寿命很长的东西引用。你没有说这是什么样的应用程序——asp.net、WPF、winforms等等,所以我们必须做出一些猜测。

您可以尝试的一种策略是日志记录。你说有3900个"父对象"的实例正在添加一些东西——你能在接受新对象的父对象上插入方法吗?也许通过记录这些添加,你可以了解它们的来源。

我认为您使用的是SOS。一个更好的选择是使用PSSCOR2或PSSCOR4(取决于运行时的版本)。!dumpheap的PSSCOR版本有一个额外的delta列,这可能有助于您检测哪些实例随着时间的推移而增长。

您可以在父类型的所有对象上使用!objsize

.foreach (address {!dumpheap -short -type MyParentType}) {!objsize ${address}}

如果您的类名不够唯一,则通过方法表

 !name2ee MyModule MyParentType ; *** to get the method table
 .foreach (address {!dumpheap -short -mt <methodtable>}) {!objsize ${address}}