Analyzing Memory Leaks from Dump Files with SciTech .NET Memory Profiler

November 18, 2011

no comments

I had to analyze a memory leak the other day and all I was provided by the customer was a couple of dump files from two points in the application’s lifetime—one dump immediately after initialization, and another dump after the memory leak has accumulated. This is an ideal scenario: now “all it takes” is to compare the two dumps and see which objects are “growing” in memory. That’s, of course, if the leak is actually in managed objects—which isn’t always the case (and VMMap is your friend here).

Naturally, analyzing memory leaks is not always easy, and even if you have a couple of dumps you can spend a very long time in a dark room with WinDbg and SOS and still have no idea where the leak is coming from. Two things that could help immensely with diagnosing memory leaks in complex heap dumps are:

Dominator set analysis—instead of focusing on the myriads of objects occupying memory and trying to figure out the retention chain of each object, dominator set analysis tries to find the objects directly responsible for keeping a large number of other objects alive1. (The Eclipse Memory Analyzer Tool can find dominator sets for large Java heap dumps.)

Visualizing heap dumps—until not long ago, the state of the art in .NET memory dump analysis was running a bunch of WinDbg commands, sometimes assisted by CLR Profiler’s poor visualization features and individual-object-level commands like !vcgroot. Naturally, there are profilers that can visualize snapshots from a live application’s heap; but doing the same for a memory dump is usually impossible.

SciTech’s .NET Memory Profiler can do both. It can import memory dumps as if they were live heap snapshots taken by the profiler, and it can perform dominator set analysis to display the number of objects retained uniquely by another object2.

Full disclosure: I was given a license for the Professional version of the .NET Memory Profiler (v4.0). Nonetheless—and you know this—the following is an unbiased walkthrough through one of the product features.

First things first: we open the Memory Profiler and choose File | Import memory dump. This takes a while—I suspect that the profiler is converting the dump to an internal representation used in the standard snapshots.


We do the same for any additional dumps. Generally, the import process should be linear in the number of objects in the heap dump. When the analysis completes, we can choose the snapshots to compare:


(Naturally, I am not using customer-provided dumps here to prevent information disclosure. Instead, these dumps are taken from a memory leak analysis exercise in the .NET Debugging course.)

Now begins the fun, which I can only describe in a few screenshots and leave the rest to the profiler’s documentation and tutorials. The first thing you’ll see is a list of “issues”—and in this case, I’ve got some instances directly rooted by an EventHandler, and some other instances indirectly rooted by an EventHandler. While this isn’t necessarily a memory leak, it’s certainly suspicious and worth further analysis.

(click the image to enlarge it)

After clicking on MainForm.FileInformation, I get the root paths and an instance list for the suspicious objects. Here’s the root path:

(click the image to enlarge it)

…and here’s the instance table—for each object, the “Held bytes” column is the object’s dominated set’s size:


We see easily that there is a single root path for a large number of instances by clicking the type name. Alternatively, we could focus on the root itself and visualize the graph stemming from it:


To summarize, by allowing to import memory dumps and providing easy visualization, multiple root path traversal, instance- and type-level information, and dominated-set analysis – SciTech Memory Profiler has already helped me pinpoint a real memory leak (in the less than 24 hours since I got the license :-)).

The example above only scratches the surface of what modern profilers can do for you. If you are one of the hardcore pros still using !gcroot and !dumpheap for all your leak analysis needs, that’s great—but if you want to save time and have a tool detect some of the common issues automatically, use a profiler first.

I have been recently posting short updates and links on Twitter as well as on this blog. You can follow me: @goldshtn

[1] To formalize: for each heap object X there is a (possibly empty) set of roots {R1, …, Rn} keeping the object alive, i.e. each Ri is a root and there is a reference path from Ri to X. Then, we can define {D1, …, Dn} the dominator set of X where Di is the object closest to X on the reference path from Ri to X such that if Di were removed from the reference path, there would no longer be a path from Ri to X.

[2] I.e., for an object D it can find the dominated set {X1, …, Xm} such that D is in the dominator set of each Xi.

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>