Dela via


Tool for generating DGML graphs showing why your object can’t be collected (VisualGCRoot)

Visual Studio.NET 2010 has a new feature that allows you to create nice directed graphs with a markup language called DGML (Directed Graph Markup Language). 

Visualizing object graphs with DGML

Chris Lovett wrote a tool that takes GCRoot output and transforms it to a DGML document so that you can see the roots of an object in a more visual way, and finally Mohamed Mahmoud went one step further and made a debugger extension that does this for you directly.   

The debugger extension is called VGCRoot and you can get the extension, and some instructions and demos for it here.

The VGCRoot extensions

If you are looking at a memory dump in windbg and try to figure out why your object is still sticking around, collection after collection, you can use the sos extension to run a command called !GCRoot which will give you a textual representation of how your object is rooted. 

In other words, it will give you several “stacks” linking your object all the way up to one or more “roots”, where the roots may be threads, static objects, reference counted objects and until you break the chain between the root and your object your object can’t be garbage collected.

A typical root chain looks something like the one below taken from one of my memory investigation posts

 0:000> !gcroot 00000000800dfb98 
... DOMAIN(000000000017E210):HANDLE(Strong):4b41308:Root: 00000000c0020990(System.Threading._TimerCallback)-> 
00000000c0020908(System.Threading.TimerCallback)-> 
00000000c001b530(System.Web.Caching.CacheExpires)-> 
00000000c001b568(System.Object[])-> 
00000000c001bef8(System.Web.Caching.ExpiresBucket)-> 
00000001008fbf40(System.Web.Caching.ExpiresPage[])-> 
00000001008fbff8(System.Web.Caching.ExpiresEntry[])-> 
000000010001ebd8(System.Web.Caching.CacheEntry)-> 
000000010001eb98(System.Web.SessionState.InProcSessionState)-> 
00000000800dd340(System.Web.SessionState.SessionStateItemCollection)-> 
00000000800dd3f0(System.Collections.Hashtable)-> 
00000000802fe7e0(System.Collections.Hashtable+bucket[])-> 
00000000800e09e8(System.Collections.Specialized.NameObjectCollectionBase+NameObjectEntry)-> 
00000000800dfb98(System.Xml.XmlDocument) 

In this case we have an XmlDocument that can’t be garbage collected because it is stored in session scope so until it is removed from session scope (breaking the link between XmlDocument and SessionStateItemCollection)  it can’t be garbage collected.

With !VGcRoot we can now get all the roots in a DGML file that we can open up in Visual Studio .NET 2010, making this much easier to digest.

You run it from windbg using !vgcroot /do /fields <objectaddress> [<DGML File path>] and the resulting graph (in this case for a Form object) looks like this.   

Field Names

Here we can see for example that the Form is linked by a UserPreferenceChangedEventHandler through the _target member variable, in other words, one reason that the Form can’t be garbage collected is because it is handling a UserPreferenceChangedEvent.

I will probably be showing this off more in context in future memory investigation posts but just wanted to show off the extension so that you can start playing around with it.  Be sure to check out his post to see other stuff you can do with the graph once you have it generated.

Have a good one,

(and thanks to Mohamed for writing the extension)

Tess

Comments

  • Anonymous
    March 03, 2010
    Awesome.  I almost can't wait to have my next GC issue!

  • Anonymous
    March 03, 2010
    The comment has been removed

  • Anonymous
    March 03, 2010
    Awesome tool, thanks. In your March 1st post you talked about "... object is not necessarily rooted but it still doesn’t get collected" and solving this with the new !GCWhere, !FindRoots !HandleCLRN commands. So will !VGcRoot handle the case where the object is not necessarily rooted? thanks, Marc

  • Anonymous
    March 04, 2010
    Looking at this post: http://blogs.msdn.com/terryclancy/archive/2009/05/20/visual-studio-team-system-2010-new-features-extensibility-points-and-partner-opportunities.aspx it seems you'll need VSTS2010 Architecture to be able to view DGML files. Is this true, or just for the architecture viewer? It seems like a valuable tool to present all sort of directed graphs, from Visual Studio Addins for example.

  • Anonymous
    March 04, 2010
    Marc, No it wont catch that case.  Basically what vgcroot does is looks at gcroot output and creates a DGML graph for it.  In other words if your object is not strongly rooted, there isn't a rootgraph for it so it wont show up in vgcroot either. Sander, I am not sure which SKUs this is in, I'll have to check on that, but given that DGML is just a straight XML file I think there might be a chance that other viewers pop up as well (outside of visual studio) in the future.  If I dream a little, the optimal thing would be for the extension to just pop up a window from windbg with the rootgraph without even having to open it up separately in visual studio. Btw, glad you all liked the tool, i'll send the feedback to Mohamed to see if perhaps there is even more improvements/features that could be added to make it even more useful.   The usefulness for me in support is obviously that I now have a more visual representation that I can use in my discussions with my customers, but again the ideal scenario is if these issues can be resolved already at the dev stage without even having to contact support...

  • Anonymous
    March 04, 2010
    Thank you very much for the kind words, please let me know if you have any feature requests or improvements to the extension.

  • Anonymous
    March 08, 2010
    You can also view DGML files in VS 2010 Premium.