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:
The profiler’s operation mode is roughly the following:
- Run the application and capture a snapshot of its memory usage before exercising the leaking scenario
- Exercise the leaking scenario
- Capture additional snapshots during and after the scenario’s execution
- 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:
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:
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:
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”:
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).