private static void PopulateRootObject(ClrRootRefModel rootRef, ClrHeap heap) { var rootObject = new ClrObjectModel { TypeName = rootRef.RootObjectTypeName, Address = rootRef.RootObjectAddress, ReferencedObjects = new List <ClrObjectModel>() }; (uint count, ulong toltalSize) = PopulateReferencedObjects(heap, rootObject); rootObject.TotalSize = toltalSize; rootRef.ObjectCount = count; rootObject.ChildCount = rootRef.ObjectCount - 1; rootRef.RootObject = rootObject; }
private static (uint, ulong) PopulateReferencedObjects(ClrHeap heap, ClrObjectModel clrObjModel) { // Evaluation stack var eval = new Stack <ulong>(); var addressToClrObjectModel = new Dictionary <ulong, ClrObjectModel> { { clrObjModel.Address, clrObjModel } }; // To make sure we don't count the same object twice, we'll keep a set of all objects // we've seen before. Note the ObjectSet here is basically just "HashSet<ulong>". // However, HashSet<ulong> is *extremely* memory inefficient. So we use our own to // avoid OOMs. var currentObj = clrObjModel.Address; var considered = new ObjectSet(heap); uint count = 0; ulong size = 0; eval.Push(currentObj); while (eval.Count > 0) { // Pop an object, ignore it if we've seen it before. currentObj = eval.Pop(); if (considered.Contains(currentObj)) { continue; } considered.Add(currentObj); // Grab the type. We will only get null here in the case of heap corruption. ClrType type = heap.GetObjectType(currentObj); if (type == null) { continue; } count++; size += type.GetSize(currentObj); // Now enumerate all objects that this object points to, add them to the // evaluation stack if we haven't seen them before. type.EnumerateRefsOfObject(currentObj, delegate(ulong child, int offset) { if (child != 0 && !considered.Contains(child)) { var childObj = heap.GetObject(child); ClrObjectModel childClrModel = null; if (addressToClrObjectModel.ContainsKey(childObj)) { childClrModel = addressToClrObjectModel[childObj]; } else { childClrModel = new ClrObjectModel { TypeName = childObj.Type.Name, Address = childObj, ReferencedObjects = new List <ClrObjectModel>(), }; addressToClrObjectModel[currentObj] = childClrModel; } addressToClrObjectModel[currentObj].ReferencedObjects.Add(childClrModel); eval.Push(child); } }); } return(count, size); }