Alois Kraus February 2016

What is the ClrMD equivalent to !DumpHeap -live?

ClrMD is a great tool to inspect a live executable or a memory dump. To dump all managed heap objects as summary you can use

https://blogs.msdn.microsoft.com/dotnet/2013/05/01/net-crash-dump-and-live-process-inspection/

var stats = from o in heap.EnumerateObjects()
            let t = heap.GetObjectType(o)
            group o by t into g
            let size = g.Sum(o => (uint)g.Key.GetSize(o))
            orderby size
            select new
            {
                Name = g.Key.Name,
                Size = size,
                Count = g.Count()
            };

foreach (var item in stats)
    Console.WriteLine("{0,12:n0} {1,12:n0} {2}", item.Size, item.Count, item.Name);

That works great and is the equivalent of !DumpHeap -stat in Windbg with the SOS Extension. For regression testing it is often desireable to check after a test if objects were leaked. That looks like a perfect fit for the code above but unfortunately it produces false positives because there may be objects which are no longer rooted but they are still reported in the summary. That can lead to reported leaks although there are none.

SOS has mitigated this issue by addine to !DumpHeap the -live switch. What would be the equivalent ClrMD code to get only the live objects so regression tests only fail for a real reason?

I guess I need to use ClrType.EnumerateRefsOfObjectCarefully to walk the stack recursively until I find a root object (ClrHeap.EnumerateRoots) but that approach needs many temporary Hashsets to track recursive object graph. Is this the only way to do it or is there somewhere inside MS alre

Answers


Alois Kraus February 2016

I have found some nice blog at https://harshaprojects.wordpress.com/2015/12/29/clr-md-analyzing-live-process/#comment-32 which contains exactly what I am after. For completeness I post the code here.

The ObjectSet class is a more memory efficient HashSet because HashSet caused OOMs on the authors machine. I use EnumerateRefsOfObjectCarefully because that is the same method which PerfView uses (for a reason I guess).

That is now also part of my open source WMemoryProfiler v.2.2

https://wmemoryprofiler.codeplex.com/releases/view/619764

which lets you choose Windbg with SOS or ClrMD to automate the analysis of processes.

    private static ObjectSet GetLiveObjects(ClrHeap heap)
        {
            ObjectSet considered = new ObjectSet(heap);
            Stack<ulong> eval = new Stack<ulong>();

            foreach (var root in heap.EnumerateRoots())
                eval.Push(root.Object);

            while (eval.Count > 0)
            {
                ulong obj = eval.Pop();
                if (considered.Contains(obj))
                    continue;

                considered.Add(obj);

                var type = heap.GetObjectType(obj);
                if (type == null)  // Only if heap corruption
                    continue;

                type.EnumerateRefsOfObjectCarefully(obj, delegate(ulong child, int offset)
                {
                    if (child != 0 && !considered.Contains(child))
                        eval.Push(child);
                });
            }

            return considered;
        }

    class DumpDiffEntry
    {
        public ClrType Type;
        public int Count;
        public long Size;
    }

    class Entry
    {
        public string Name;
      

Post Status

Asked in February 2016
Viewed 2,926 times
Voted 12
Answered 1 times

Search




Leave an answer