public void AddObject(TypeInfo typeInfo, HeapObjectEvent heapObjectEvent) { if (heapObjectEvent.ObjectSize == 0) { // This means it's just reporting references // TODO: Validate if we need to handle it. return; } string typeName = typeInfo.Name; long typeId = typeInfo.TypeId; long address = heapObjectEvent.ObjectPointer; if (trackedTypeNames.Remove(typeName)) { TrackedTypes.Add(typeName, typeId); } if (!Types.TryGetValue(typeId, out var heapTypeInfo)) { Types[typeId] = heapTypeInfo = new HeapshotTypeInfo(typeInfo); } var heapObject = GetOrCreateObject(address, heapTypeInfo); Graph.AddVertex(heapObject); foreach (var reference in heapObjectEvent.References) { var referencedObject = GetOrCreateObject(reference.ObjectPointer, null); Graph.AddEdge(new Edge <HeapObject> (heapObject, referencedObject)); } }
string ReportPathsToRoots(Heapshot heapshot, HeapshotTypeInfo typeInfo, string iterationName, out int objectCount) { var visitedRoots = new HashSet <HeapObject> (); string outputPath = null; var rootTypeName = typeInfo.TypeInfo.Name; var objects = typeInfo.Objects; objectCount = objects.Count; // Look for the first object that is definitely leaked. foreach (var obj in objects) { visitedRoots.Clear(); bool isLeak = false; var paths = heapshot.Graph.GetPredecessors(obj, vertex => { if (heapshot.Roots.TryGetValue(vertex.Address, out var heapRootRegisterEvent)) { visitedRoots.Add(vertex); isLeak |= IsActualLeakSource(heapRootRegisterEvent.Source); } }); if (outputPath == null && isLeak) { var objectRetentionGraph = new AdjacencyGraph <HeapObject, SReversedEdge <HeapObject, Edge <HeapObject> > > (); foreach (var root in visitedRoots) { if (paths.TryGetPath(root, out var edges)) { objectRetentionGraph.AddVerticesAndEdgeRange(edges); } } var graphviz = objectRetentionGraph.ToLeakGraphviz(heapshot); var dotPath = Path.Combine(graphsDirectory, iterationName + "_" + rootTypeName + ".dot"); outputPath = graphviz.Generate(DotEngine.Instance, dotPath); } else { objectCount--; } } // We have not found a definite leak if outputPath is null. return(outputPath); }
HeapObject GetOrCreateObject(long address, HeapshotTypeInfo heapshotTypeInfo = null) { if (!Objects.TryGetValue(address, out var heapObject)) { Objects[address] = heapObject = new HeapObject(address); } if (heapObject.TypeInfo == null && heapshotTypeInfo != null) { heapObject.TypeInfo = heapshotTypeInfo.TypeInfo; heapshotTypeInfo.Objects.Add(heapObject); } return(heapObject); }
public bool TryGetHeapshotTypeInfo(long typeId, out HeapshotTypeInfo heapshotTypeInfo) => Types.TryGetValue(typeId, out heapshotTypeInfo);
public bool TryGetHeapshotTypeInfo(string name, out HeapshotTypeInfo heapshotTypeInfo) { heapshotTypeInfo = null; return(TrackedTypes.TryGetValue(name, out var typeId) && TryGetHeapshotTypeInfo(typeId, out heapshotTypeInfo)); }