.NET Memory Analysis: Object Inspection

.NET Memory Analysis: Object Inspection

Rate This
  • Comments 10

In Visual Studio 2013, we introduced a way to analyze .NET Memory with Visual Studio. Now in the Update 2, we’ve added a new feature to inspect values of objects and instances to improve your diagnostic capabilities. You can follow along using the same code and dumps from the SampleLeak App we had in the previous walkthrough.

If you are using Managed GCDumps in DiagSession files from Application Insights for Azure (like from this blog post), you will not have heap to inspect Instances and Values. This feature requires dumps with heap to have the information required for object inspection.

Instance View

While on the type summary page, we no longer show a drop down expansion of instances in a type. Instead we pop an icon to enter the new instance view. You can enter this view by clicking the icon or pressing Enter.

This opens up a new instance view for you to dig deeper into your dump. You can edit the default value shown (instead of just the Type) by adding a DebuggerDisplayAttribute to your code. Hovering over items will pop a DataTip to inspect the values for those instances. You can expand down the objects to inspect the data in the subfields. If you want to dig deep down without a DataTip, you can enter into Quick Watch by pressing Enter with the entry selected or through the context menu.

With this inspection, you can see that all the User entries contained the same Id (your cache isn't working as expected and you're creating duplicate entries) and that BinaryData is containing an excessively large bulk of the allocation of the User object.

This also applies in the Paths to Root and Referenced Objects graph at the bottom.

To return to the previous type overview, you can either select Type from the breadcrumbs at the top or hit the Back button or your Backspace key.

In Closing

With the addition of these enhancements, we hope these new features will give you more insight to what’s happening inside your .NET Memory dumps. If you wish to know more about .NET Memory Analysis in general, please revisit our two previous blog entries on the subject. If you have any questions or comments, please leave them in the comments below or in our MSDN forum.

Leave a Comment
  • Please add 4 and 8 and type the answer here:
  • Post
  • Is there any way in C# code to ensure that an object is no longer referenced?   We'd put a call to that in our complex object's dispose method to ensure that public member variables, public properties, public event handlers in the current object are not referenced by something outside of the current object.

    Something like System.Diagnostics.Debug.ReferencedOneTime( object ) which returns true if there is only one reference to an object; false otherwise.  This would let us check the members of the current object during the current object's dispose method.  

    This is quite handy in a complex MVVM wpf application with the event subscritpion

  • Fundamentally we don't track the creation of references to particular objects.   The only way you can determine how many references something has is to do a GC, and only then you only know that the reference count from LIVE objects is zero (thus it gets scheduled for finalization).  

    It is not clear what your goal actually is, but you may be able to achieve it 'after the fact' by freeing the subscription and seeing if the object dies.   similarly, you could imagine creating a NEW object and putting it in place of the object of interest and dropping references to it.   If that object does not die (that is its finalizer does not fire), on the next full GC you know that something is keeping it alive that you did not wish to have.  

    The other alternative is to use a profiler to check the 'one reference' invariant.    PerfView takes heap dumps and each of those dumps can be a full object graph, and supports 'referred by' queries.  Thus it is straightforward to alert if you find that objects of a certain type (or pointed to from certain objects) have no other references to them.

  • Here's an example:

    1.  Our main application is running, let's say it's WPF/C#

    2. User clicks on a launch window X button

    3. Window X launches

    4. Window X does a bunch of things, handles user interaction

    5. The user clicks on a button to close window X

    6. Window X is closed

    7.  Window X dispose is called

    It would help in step 7 to determine if any resource allocated by the window is still active or referenced by anything outside of Widow X's class.

    It would also help to determine if Window X has allocated any resources that have not been disposed of.

    At the end of Window X's dispose method we could include a System.Diagnostics.Debug call to ensure that all of the members of Windows X's class are not referenced by any class other than Window X.

    This would be in System.Diagnostics.Debug as it is for diagnostic purposes.

  • @Ted

    Can you log a visualstudio.uservoice.com request for this? That is how we track user suggestions to see how popular they are.

    Thanks!

  • @Ted, unfortunately this is not possible today using code in your program.  The easiest way to do it would be to take a snapshot (i.e. in the case of this tool a dump) before step 1, then a second snapshot after step 7, and then diff the first with the second to see if any counts have increased (it sounds like you are asserting that the instance count should be identical).  

    However, thank you for the suggestion regarding the ability to do this programmatically, it is something we will take into consideration for the future.

  • What's the best way to analyze objects making it to Gen2, only to be collected later, to determine whether we can make them not be, thus minimizing the impact of GC2 collections in our application?

  • @Matt

    PerfView does have a view that may be helpful here.  

    Basically if you ask PerfView to collect ‘.NET SampAlloc’ events it will log an event when objects are allocated (and when GC’s collect them). (The app has to start AFTER you start data collection).  

    When you view the data, you will get a view that includes ‘Gen 2 Object Deaths’ which will show you all the object that died in Gen 2.  

    Download: www.microsoft.com/.../details.aspx

    Tutorial: channel9.msdn.com/.../PerfView-Tutorial

    blogs.msdn.com/.../publication-of-the-perfview-performance-analysis-tool.aspx

  • @Maria:

    Thanks for the info, but a colleague have been investigating perfiew for more than a day, and although can find 'Gen 2 Object Deaths’ described in the help, we cannot find it anywhere in the actual results analysis. And yes, we did start them in the right order in the right options.

    The videos you point to do not help very much since they are for very basic scenarios

    Can you help further?

    Matt

  • @Matt

    Here are the steps I've follow just now and was able to see it:

    -Start PerfView

    -Go to Collect menu, choose Collect,

    -From there, choose Advanced, .NET SampAlloc, Click Start Collection

    -Run app

    -Stop Collection from that Collecting data... window.

    -It will take a while (it will say Working in the lower right corner)

    -When it's done, in the main PerfView window, in the left side, under PerfViewData.etl you will have a list with: TraceInfo, processes, Event, CPU Stacks, GC Heap Alloc Stacks, etc., Gen 2 Object Deaths Stacks

  • @Maria,

    Got it. I think maybe I started my process too early. thx Matt

Page 1 of 1 (10 items)