Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Identify where Instances of an object are Still Referenced?

Tags:

c#

.net

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.

like image 256
Mehdi LAMRANI Avatar asked Apr 28 '11 12:04

Mehdi LAMRANI


2 Answers

  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.

like image 105
Richard Szalay Avatar answered Sep 23 '22 07:09

Richard Szalay


EDIT 2018: if you have visual studio 2015+ then the whole process is much simpler: MSDN tutorial.

if you want to know exactly which instances are alive , all you need to do is take a process dump with Adplus, that comes with the debugging tools for windows. (its now part of the SDK download.)

then in WinDBG, use the !dumpheap -type command to see what instaces of which classes are still up.

then you can use the !gcroot to see who is holding that reference.

like image 29
Menahem Avatar answered Sep 22 '22 07:09

Menahem