如何确定一个对象的实例仍然被引用? [英] How to Identify where Instances of an object are Still Referenced?

查看:141
本文介绍了如何确定一个对象的实例仍然被引用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

运行VS2010的探查与对象生存跟踪我的应用程序后,我有这样一个特定的类:

实例 ---------- 1 418 276
%总计实例--------------------- 5.8%
总字节数分配------- 158 846 912
%总字节数--------------------------%5.94
第0实例收集--------- 5 196
1代实例收集-------- 54 894
Gen 2的实例收集 ---- 747 874
实例活在结束 --------- 610 312
第0字节收集----------- 581 952
创1字节收集--------- 6 148 128
创2个字节收集--------- 3 761 888

正如你易拉罐看到,半数创建的实例最终主要表现为第二代另一半则是活着,直到应用程序的结束。 [哈,哈,哈,哈,活着,活着... 的 - >的好了,对不起,我could'nt抗拒... 的]

让我困扰的是,这种情况下应该有一个很短的寿命(这基本上是一个数据域类 - 这可能是一个结构,但我preferred,使之成为一流的激活GC就可以了)。 通过阅读非常大的二进制文件(每行是一个类/记录)通过小规模的队列代表/事件,基本上只是读它,把它放在队列工人(这是
这些实例被创建,并通过极有规律的出队),然后终止(背景工人正常结束)。我想事件是取消订阅当工人没有更多的存在。

因此​​,有没有办法来确定哪些是这些引用隐藏?因为如果他们不GC'd他们仍然被引用的地方,但如何确切地回答?我累了猜测和尝试这么多的假设,所以如果有人有更合理的准则或公正的清单和/或工具/ precise探查地方看看,我欢迎它。

资源互补的答案
通过DGML可视GCRoot - 由于理查德·绍洛伊
此外,该视频 GCRoot演示由克里斯·洛维特是非常教育性的拍摄对象。

解决方案
  1. 启用非托管的调试在项目属性的调试标签
  2. 运行应用程序,并要考察的类型设置一个断点在点
  3. 立即的窗口中,键入:

  .load SOS
!DumpHeap型<部分机型名称>
 

这将返回类似:

 地址MT尺寸
026407c0 53ecee20 16
 

然后你就可以走了地址和使用 GCRoot 找到在那里它的根:

 !GCRoot 026407c0
 

<一个href="http://www.lovettsoftware.com/blogengine.net/post/2010/01/15/Visualizing-Runtime-Object-Graphs.aspx"相对=nofollow>克里斯·洛维特(通过<一个href="http://blogs.msdn.com/b/tess/archive/2010/03/03/tool-for-generating-dgml-graphs-showing-why-your-object-can-t-be-collected-visualgcroot.aspx"相对=nofollow>苔丝Ferrandez )创造了一个非常整洁的工具,它的低级别的转换 GCRoot 输出到一个DGML图可能更容易诊断

另外,穆罕默德·马哈茂德·创造了一个的调试器扩展,使您产生从WinDBG的图形,但它并没有在Visual Studio中的工作,所以你可能要坚持到克里斯的工具,以避免在安装调试工具。

说了这么多,该文本输出可能是足以让你追踪下来。如果你想在GCRoot的输出信息,键入即时窗口!帮助GCRoot

After running the VS2010 profiler with Object Lifetime Tracking in my app, I have this on a particular class :

Number of Instances----------1 418 276
%Total Instances --------------------- %5.8
Total Bytes Allocated ------- 158 846 912
%Total Bytes -------------------------- %5.94
Gen 0 Instances Collected --------- 5 196
Gen 1 Instances Collected --------54 894
Gen 2 Instances Collected ----747 874
Instances Alive At End --------- 610 312
Gen 0 Bytes Collected ----------- 581 952
Gen 1 Bytes Collected ---------6 148 128
Gen 2 Bytes Collected ---------3 761 888

As you cans see, half of all created instances end up mainly as Gen 2, and the other half is staying alive until the end of the App. [ha, ha, ha, ha, staying alive, staying alive... -> Ok sorry, I could'nt resist...]

What bothers me is that these instances should have a very short lifetime (It's basically a datafield class - that could be a struct, but I preferred to make it a class to "activate" GC on it).
These instances are created by reading very large binary files (each line being a class/ a record) and passed via a small sized queue by delegate/event to workers that basically just read it, put it in queues (which are very regularly dequeued), and then terminate (background workers ending normally). I guess Events are unsubscribed to when workers no more exist.

So, is there a way to identify where are these references hiding ? Because if they are not GC'd they ARE still referenced somewhere, but how to tell for sure ? I'm tired of guessing and trying so many hypothesis SO if somebody has more rational guidelines or a fair checklist and/or tools / precise profiler places to look at, I welcome it.

Complementary Resources to the Answers
Visual GCRoot via DGML - Thanks to Richard Szalay
Also, this video GCRoot Demo from Chris Lovett is very educative on the subject.

解决方案

  1. Enable Unmanaged Debugging in the "Debug" tab of your project properties
  2. Run the application and set a breakpoint at a point where you want to investigate the types
  3. In the Immediate window, type:

.load sos
!DumpHeap -type <partial type name>

This will return something like:

 Address       MT     Size
026407c0 53ecee20       16     

Then you can take the Address and use GCRoot to find the where it's rooted:

!GCRoot 026407c0

Chris Lovett (via Tess Ferrandez) created a very neat utility that converts the low-level GCRoot output into a DGML graph which might make it easier to diagnose.

Alternatively, Mohamed Mahmoud created a debugger extension that enables you generate the graph from WinDBG, but it doesn't work within Visual Studio so you might want to stick to Chris's utility to avoid installing the Debugging Tools.

Having said that, the textual output may well be enough for you to track things down. If you want information on the output of GCRoot, type !help GCRoot in the immediate window.

这篇关于如何确定一个对象的实例仍然被引用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆