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.EnumerateRefsOfObject(obj, delegate(ulong child, int offset) { if (child != 0 && !considered.Contains(child)) { eval.Push(child); } }); } return(considered); }
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.EnumerateRefsOfObject(obj, delegate(ulong child, int offset) { if (child != 0 && !considered.Contains(child)) eval.Push(child); }); } return considered; }
static void Main(string[] args) { bool stat, live; string dump, dac; if (!TryParseArgs(args, out dump, out dac, out stat, out live)) { Usage(); Environment.Exit(1); } try { ClrRuntime runtime = CreateRuntime(dump, dac); ClrHeap heap = runtime.GetHeap(); ObjectSet liveObjs = null; if (live) { liveObjs = GetLiveObjects(heap); } Dictionary <ClrType, Entry> stats = new Dictionary <ClrType, Entry>(); if (!stat) { Console.WriteLine("{0,16} {1,12} {2}", "Object", "Size", "Type"); } foreach (ClrSegment seg in heap.Segments) { for (ulong obj = seg.FirstObject; obj != 0; obj = seg.NextObject(obj)) { if (live && !liveObjs.Contains(obj)) { continue; } // This gets the type of the object. ClrType type = heap.GetObjectType(obj); ulong size = type.GetSize(obj); // If the user didn't request "-stat", print out the object. if (!stat) { Console.WriteLine("{0,16:X} {1,12:n0} {2}", obj, size, type.Name); } // Add an entry to the dictionary, if one doesn't already exist. Entry entry = null; if (!stats.TryGetValue(type, out entry)) { entry = new Entry(); entry.Name = type.Name; stats[type] = entry; } // Update the statistics for this object. entry.Count++; entry.Size += type.GetSize(obj); } } // Now print out statistics. if (!stat) { Console.WriteLine(); } // We'll actually let linq do the heavy lifting. var sortedStats = from entry in stats.Values orderby entry.Size select entry; ulong totalSize = 0, totalCount = 0; Console.WriteLine("{0,12} {1,12} {2}", "Size", "Count", "Type"); foreach (var entry in sortedStats) { Console.WriteLine("{0,12:n0} {1,12:n0} {2}", entry.Size, entry.Count, entry.Name); totalSize += entry.Size; totalCount += (uint)entry.Count; } Console.WriteLine(); Console.WriteLine("Total: {0:n0} bytes in {1:n0} objects", totalSize, totalCount); } catch (Exception ex) { Console.WriteLine("Unhandled exception:"); Console.WriteLine(ex); } }