ANTS Memory Profiler

ANTS Memory Profiler 5.1

Introduction

As the complexity of your software rises, the chances of things going awry can too. Noticing the rising use of memory and having to restart an application after a few hours of operation could point to memory leaks.
Finding memory leaks is not an easy job but today we’re taking a look at a tool from RedGate to help us on our way to diagnose, locate and plug leaks in your .NET applications.


ANTS Memory Profiler in its fifth major release from RedGate Software which allows you to profile a multitude of different types of .NET Applications written in C#, VB.NET or MC++.
RedGate ANTS Memory Profiler

  • .NET Windows Forms Applications
  • .NET Windows Services
  • COM+ Servers
  • XAML Browser Applications
  • ASP.NET Web Applications - hosted in IIS
  • ASP.NET Web Applications – hosted in a development server
ANTS Memory Profiler is able to profile applications written for the following versions of .NET (and their architectures):
  • .NET 1.1 (x86 only)
  • .NET 2.0 / 3.0 (x86/x64)
  • .NET 3.5 (x86/x64)
The idea behind ANTS Memory Profiler – like most memory profilers, is to take snapshots of your running application at various determined points. Then, compare these snapshots to determine whether objects you expect to have been disposed have in fact been garbage collected. Sometimes you may find objects hanging around even after you’ve called Dipose on them.
We’ll be taking a deeper look at ANTS Memory Profiler using the MySLeakyApplication Windows Forms project attached – written in Visual Studio 2008 using .NET 3.5.

Marching on with ANTS Memory Profiler

ANTS Memory Profiler Settings
We start off by asking ANTS Memory Profiler to ‘Monitor disposal of objects’ which will tell us if objects still remain in memory after we call the Dispose method on them. First thing we notice when we ‘Start Profiling’ is that ANTS Memory Profiler gives you a timeline (based on Performance counters selected) of the Bytes in heap (right up the top) so you can monitor heavy usage over time.
Performance counters
This is also where we ask ANTS Memory Profiler to a ‘Take Memory Snapshot’. Generally, it’s best to take an initial snapshot as soon as the application launches to give you a baseline to begin with, and then take others where you want to ensure that the application is correctly cleaning itself up. For our application, after loading ‘Take Memory Snapshot’, open a few documents and take another, close them and take another.
Whilst you were taking your Memory snapshots, ANTS Memory Profiler was busily working out various metrics and trying to find-out about the state of objects. After consolidating all the data it will present you with a summary allowing you to drill through to find the causes of any leaks. This is where ANTS Memory Profiler really shines. Not only does it show you numbers, but as we will see, it will also present this data in a usable visual fashion.
ANTS Memory Profiler has five distinct views (grouped into 3 different types). First we have a Summary view which gives us a general overview of what ANTS Memory Profiler was able to determine about the session – by default by comparing to the previous snapshot.
Summary view
Next we have the ‘Class List’ pane which shows the namespaces/class names in question along with the actual live size (in bytes) and any changes and how many instances currently reside (including deltas). This is nicely presented to the user with visual cues, all columns are sortable and as an extra helping hand, the classes that belong in the application you’re profiling are marked in bold.
Class list
ANTS Memory Profiler works out various tid-bits about the classes in memory and lets you focus on a particular area by using some powerful Filters. These filter just the things we need to see – rather than the whole shebang.
Some of the standard filters available are:
  • Disposed objects which are still in memory

    This will track down any objects that we have actually called Dispose on but are still held in memory and cannot be garbage collected. This is the first sign that the objects that appear on this list are referenced by another object – or maybe a leaking event handler.
  • Objects on the [ Gen x | Large object] heap

    These are objects that in the particular heap selected.
  • Objects on the finalizer queue but not disposed

    These objects are ones that we should have called Disposed on. There are two very useful filters that will tell you immediately whether you have a possible memory leak.
  • ####Kept in memory only by event handlers
  • ####Kept in memory only by disposed objects.
If there are objects in either filter, you will have to spend some time analysing to plug it. But fear not! ANTS Memory Profiler will give you much more help than just tell you there are some objects that are stuck in memory.
If that wasn’t enough we can filter results even better by using the ‘Advanced Filters’ which deal with only showing certain namespaces, pinned objects, memory by instance and the list goes on!
Lets filter these results by objects that are on the finalizer queue but have not been disposed – so this implies that an object should have had its Dispose method called but we failed to do so.
Comparisons
In the above screenshot – which is comparing Snapshot 3 and 4, we find that ANTS Memory Profiler is telling us that DocumentTabPage is on the finalizer queue but has not been disposed properly.
We can ask ANTS Memory Profiler to give us a Class Reference breakdown – how the particular class references other classes. To do this, click the tree-structure like icon (left) on the selected class name list item.
Tree structure
This will show you the ‘Class Reference Explorer’ view which is presenting how our class (DocumentTabPage) relates to other classes. To the left we see instances which rely on the DocumentTabPage class directly. On the right we see instances which are referenced by instances of DocumentTabPage.
One of the things we can do here is to click on each tree node and dig deeper into that class, get an idea of live instances of the class or the instance of DocumentTabPage even during the time the snapshot was taken.
If we click the ‘System.ComponentModel.EventHandlerList’ item and click to show instances of the class we get a nice ‘Instance List’ view.
Instance list
Here we can drill into the objects and workout relationships and property information to help us determine why this was left around. There are three interesting columns in this view, first is the ‘New Object’ (first column in the picture) which tells us whether this was a new instance created between the two snapshots being compared . Then we have the ‘GC Root Object’ and ‘Distance from GC Root’ column which tells us the number of references from the root GC object to the object being analysed.
The final view ANTS Memory Profiler provides us is the ‘Object Retention Graph’ which gives you – again in a very nicely presented manner, a graph of the chains of references between the GC roots and the selected class instances.
Object retention
ANTS Memory Profiler also gives us an overview of the session and how much memory was used overall – this is found in the ‘Session Overview’ tab.
Session overview

What did we think?

Having used several profilers over the years to profile a multitude of applications, this release of ANTS Memory Profiler is a league above the rest when it comes to gathering and showing developers possible problems in code. What we really enjoyed about the profiler was that it used very little overhead – in comparison to others, which meant we were able to profile some intense applications easily.
RedGate provides a plethora of documentation for every single view and dialog – both inbuilt iconified tooltip help and well written, easy to follow documentation online and video walk throughs. The user-interface is easy to use and adapt to with lots of visual cues (icons, graphs etc.) and makes using the product seamless.
We love the filtering options that really allow us to hone in on particular areas of the code that may need reviewing. The quick view of possible leaky event handlers and disposed but still in memory filters are a godsend!
We only scratched on the main features of ANTS Memory Profiler but we encourage you to download a copy and try it on your own application and give it ago. Try the fully documented walkthrough to give you an understanding of how to use ANTS Memory Profiler.

Fixing the leak

Can you find the leak? We know that the only way we can remove tabs is by calling the CloseDocumentTab method:
private void CloseDocumentTab()
{
    if (DocumentTabs.SelectedTab != null)
    {
        TabPage document = DocumentTabs.SelectedTab;
        DocumentTabs.TabPages.Remove(document);
    }
}
If we simply call Dispose on the use of the ‘document’ variable after removing the item from the TabPages, this leak can be addressed.
private void CloseDocumentTab()
{
    if (DocumentTabs.SelectedTab != null)
    {
          TabPage document = DocumentTabs.SelectedTab;
          DocumentTabs.TabPages.Remove(document);
          document.Dispose();
    }
}

0 comments: