DCSIMG
ANTS Memory Profiler Review - All Your Base Are Belong To Us

All Your Base Are Belong To Us

Mostly .NET internals and other kinds of gory details

ANTS Memory Profiler Review

Diagnosing memory leaks by taking multiple dumps, analyzing them with SOS commands like !DumpHeap and !GCRoot, and maybe exporting a heap graph to CLR Profiler with !TraverseHeap is a very ungrateful experience albeit one I had to go through many many times.

If you’re doing postmortem diagnostics or can’t possibly afford to do live work on the problematic machine, there’s no other choice but to stick to dumps. Fortunately, in some cases you can afford to reproduce a memory leak locally and in a live scenario. In these cases, a memory profiler is an invaluable tool and can lead to much faster memory leak diagnostics without having to type and process text-mode commands. [This is not to imply that SOS skills aren’t important. The most important thing, though, is to choose the right tool for the task.]

The ANTS Memory Profiler is a profiler focused at diagnosing memory leaks and understanding memory usage in .NET applications. Its current version (v6.0) is capable of working with standard .NET executables, Windows services, ASP.NET apps and even Silverlight 4 loaded into the browser. On supported OS versions it can attach to a running process (this requires at least Windows Vista and .NET 4).

Full disclosure: I was given a complimentary copy of the profiler in exchange for this (objective! :-)) review.

There are some tutorials by RedGate that demonstrate the profiler’s capabilities, so I’ll restrict myself to an example from SELA’s .NET Debugging course. [If you’re looking for a feature comparison chart and CNET-style reviews, this isn’t what I had in mind.]

The following is a memory leak exhibited by a GUI application—when switching between directories (on the left), memory usage seems to climb significantly and never goes down:

image

The profiler’s operation mode is roughly the following:

  1. Run the application and capture a snapshot of its memory usage before exercising the leaking scenario
  2. Exercise the leaking scenario
  3. Capture additional snapshots during and after the scenario’s execution
  4. Analyze by comparing snapshots and seeing which objects are added between snapshots and are not being freed

Basically, all you have to do is run the app and remember to click “Take Memory Snapshot” in the profiler’s UI every once in a while. [I’m told that an upcoming version of the profiler will feature automatic snapshots that you can trigger from code.]

Here’s the summary view that compares two snapshots of the application—one before navigating through some folders, and one after:

image

Most of the new memory is occupied by strings, and there’s a large number of them. Starting your analysis from strings is a risky endeavor in SOS—you can quickly be paging through thousands of objects with little hope of telling the forest from the trees. With ANTS it’s simpler—just click the class you want and choose “Class Reference Explorer” from the top of the view and then click away through the reference graph:

image

This reaffirms the suspicion that the FileInformation objects have something to do with the leak. So let’s focus on these objects and see what we get:

image

Some of these objects (a mere 29%) are referenced by a listbox—that’s most probably the listbox on the right of the UI. But all of them—100%—are referenced by EventHandlers. This should immediately light up in your brain as a potential leak source, and the profiler also has an object filter for “Kept in memory only by event handlers” that I could use.

What is this event handler? We could tell by looking at one of the instances of FileInformation, through the profiler’s “Object Retention Graph”:

image

Now that’s really neat. You get the full path from the GC root—in this case a static event—to your object of interest.

This concludes the leak analysis: the strings comprise most of the memory leak, but they are held in memory by instances of FileInformation, which in turn are not reclaimed because they are registered to a static event (and probably the code that’s supposed to unregister them isn’t called, or worse—doesn’t exist).

Comments

Dennis said:

Another option to find memory leaks is the VisualStudio10 Profiler.

You can choose the "Memory Alocation" option, include the "Object Lifetime" test and run your application.

After your close the application the .NET Profiler will create a number of tables in which you can see what are the objects that your application created them the most and what objects the GC didn't collect at the end of the program.

The Profiler also displays a call tree where you can see in what method the leaking object was created the most.

# January 14, 2011 5:10 PM
Leave a Comment

(required) 

(required) 

(optional)

(required) 


Enter the numbers above: