在我的应用程序中运行带有对象生命周期跟踪的VS2010探查器之后,我在特定的类上有这个:
实例数 ---------- 1 418 276
总实例百分比---------------------%5.8
分配的总字节数------- 158 846 912
%总字节数--------------------------%5.94
Gen 0实例收集--------- 5 196
第1组实例收集-------- 54 894
第二代实例收集 ---- 747 874
最后活动 --------- 610 312
Gen 0字节收集----------- 581 952
Gen 1 Bytes Collected --------- 6 148 128
Gen 2 Bytes Collected --------- 3 761 888
正如您所见,所有已创建实例的一半最终主要为第2代,而另一半则保持活着直到应用程序结束即可。 [ ha,ha,ha,ha,活着,活着...... - > 对不起,我无法抗拒...... ]
困扰我的是这些实例的生命周期非常短(它基本上是一个数据域类 - 可能是一个结构体,但我更喜欢使它成为一个“激活”GC的类)。
这些实例是通过读取非常大的二进制文件(每行是一个类/一个记录)创建的,并通过委托/事件通过一个小型队列传递给基本上只是读取它的工作者,将它放入队列(这是非常经常出列),然后终止(后台工作人员正常结束)。我想当工人不再存在时,事件是取消订阅的。
那么,有没有办法确定隐藏这些引用的位置?因为如果他们不是GC,他们仍然被引用到某个地方,但如何确定?我厌倦了猜测和尝试这么多的假设,如果有人有更合理的指导方针或公平的清单和/或工具/精确的探查器的地方,我欢迎它。
答案的补充资源
Visual GCRoot via DGML - 感谢Richard Szalay
此外,Chris Lovett的这段视频GCRoot Demo对这个主题非常有教育意义。
答案 0 :(得分:7)
.load sos
!DumpHeap -type <partial type name>
这将返回如下内容:
Address MT Size
026407c0 53ecee20 16
然后,您可以使用Address
并使用GCRoot
查找其根源所在的位置:
!GCRoot 026407c0
Chris Lovett(通过Tess Ferrandez)创建了一个非常简洁的实用程序,可将低级GCRoot
输出转换为DGML图,这样可以更容易诊断。
或者,Mohamed Mahmoud创建了一个debugger extension,使您可以从WinDBG生成图形,但它在Visual Studio中不起作用,因此您可能希望坚持使用Chris的实用程序来避免安装调试工具。
话虽如此,文本输出可能足以让您追踪事情。如果您需要有关GCRoot输出的信息,请在即时窗口中键入!help GCRoot
。
答案 1 :(得分:2)
EDIT 2018:如果你有2015 +视觉工作室,那么整个过程就会简单得多:MSDN tutorial。
如果您想确切知道哪些实例存活,您需要做的就是使用debugging tools for windows附带的Adplus进行流程转储。 (它现在是SDK下载的一部分。)
然后在WinDBG中,使用!dumpheap -type 命令查看哪些类仍处于什么状态。
然后您可以使用!gcroot查看谁持有该引用。
答案 2 :(得分:-1)
您可以键入命令gcroot
。