void DecodeNode(NodeIndex n) { if (m_node == null) { m_node = m_graph.AllocNodeStorage(); m_nodeType = new NodeType(m_graph); } m_graph.GetNode(n, m_node); m_node.GetType(m_nodeType); }
public ObjectViewerTreeViewController(MemoryGraph graph, RefGraph refGraph, List <NodeIndex> focusNodes) { m_graph = graph; m_refGraph = refGraph; m_focusNodes = focusNodes; m_typeStorage = m_graph.AllocTypeNodeStorage(); m_nodeStorage = m_graph.AllocNodeStorage(); m_refNodeStorage = m_refGraph.AllocNodeStorage(); m_columnNames = new List <string>() { "Value", "Size", "Type" }; }
internal void ProcessHeapSnapshot() { // Constants. const string PinnedHandlesNodeName = "[Pinned handle]"; const string AsyncPinnedHandlesNodeName = "[AsyncPinned handle]"; const string OverlappedDataTypeName = "System.Threading.OverlappedData"; const string ByteArrayTypeName = "System.Byte[]"; const string ObjectArrayTypeName = "System.Object[]"; // Open the heap dump. GCHeapDump dump = new GCHeapDump(_HeapSnapshotFilePath); _ProcessID = dump.ProcessID; // Get the heap info. DotNetHeapInfo heapInfo = dump.DotNetHeapInfo; // Get the memory graph. MemoryGraph memoryGraph = dump.MemoryGraph; // Get the root node. NodeIndex rootIndex = memoryGraph.RootIndex; Node rootNode = memoryGraph.GetNode(rootIndex, memoryGraph.AllocNodeStorage()); // Allocate additional nodes and node types. Node handleClassNodeStorage = memoryGraph.AllocNodeStorage(); NodeType handleClassNodeTypeStorage = memoryGraph.AllocTypeNodeStorage(); Node pinnedObjectNodeStorage = memoryGraph.AllocNodeStorage(); NodeType pinnedObjectNodeTypeStorage = memoryGraph.AllocTypeNodeStorage(); Node pinnedObjectChildNodeStorage = memoryGraph.AllocNodeStorage(); NodeType pinnedObjectChildNodeTypeStorage = memoryGraph.AllocTypeNodeStorage(); Node userObjectNodeStorage = memoryGraph.AllocNodeStorage(); NodeType userObjectNodeTypeStorage = memoryGraph.AllocTypeNodeStorage(); Node arrayBufferNodeStorage = memoryGraph.AllocNodeStorage(); NodeType arrayBufferNodeTypeStorage = memoryGraph.AllocTypeNodeStorage(); // Create a dictionary of pinned roots by pinned object address. Dictionary <Address, PinningRoot> pinnedRoots = new Dictionary <Address, PinningRoot>(); // Iterate over the nodes that represent handle type (e.g. [AsyncPinned Handle], [Pinned Handle], etc.) for (NodeIndex handleClassNodeIndex = rootNode.GetFirstChildIndex(); handleClassNodeIndex != NodeIndex.Invalid; handleClassNodeIndex = rootNode.GetNextChildIndex()) { // Get the node. Node handleClassNode = memoryGraph.GetNode(handleClassNodeIndex, handleClassNodeStorage); NodeType handleClassNodeType = handleClassNode.GetType(handleClassNodeTypeStorage); // Iterate over all pinned handles. if (PinnedHandlesNodeName.Equals(handleClassNodeType.Name)) { for (NodeIndex pinnedObjectNodeIndex = handleClassNode.GetFirstChildIndex(); pinnedObjectNodeIndex != NodeIndex.Invalid; pinnedObjectNodeIndex = handleClassNode.GetNextChildIndex()) { Node pinnedObjectNode = memoryGraph.GetNode(pinnedObjectNodeIndex, pinnedObjectNodeStorage); NodeType pinnedObjectNodeType = pinnedObjectNode.GetType(pinnedObjectNodeTypeStorage); // Create an object to represent the pinned objects. PinningRoot pinnedRoot = new PinningRoot(GCHandleKind.Pinned); List <Address> objectAddresses = new List <Address>(); // Get the address of the OverlappedData and add it to the list of pinned objects. Address pinnedObjectAddress = memoryGraph.GetAddress(pinnedObjectNodeIndex); UInt16 pinnedObjectGeneration = (UInt16)heapInfo.GenerationFor(pinnedObjectAddress); pinnedRoot.PinnedObjects = new PinnedObject[] { new PinnedObject(pinnedObjectAddress, pinnedObjectNodeType.Name, (uint)pinnedObjectNode.Size, pinnedObjectGeneration) }; pinnedRoots.Add(pinnedObjectAddress, pinnedRoot); } } // Iterate over asyncpinned handles. if (AsyncPinnedHandlesNodeName.Equals(handleClassNodeType.Name)) { for (NodeIndex pinnedObjectNodeIndex = handleClassNode.GetFirstChildIndex(); pinnedObjectNodeIndex != NodeIndex.Invalid; pinnedObjectNodeIndex = handleClassNode.GetNextChildIndex()) { Node pinnedObjectNode = memoryGraph.GetNode(pinnedObjectNodeIndex, pinnedObjectNodeStorage); NodeType pinnedObjectNodeType = pinnedObjectNode.GetType(pinnedObjectNodeTypeStorage); // Iterate over all OverlappedData objects. if (OverlappedDataTypeName.Equals(pinnedObjectNodeType.Name)) { // Create an object to represent the pinned objects. PinningRoot pinnedRoot = new PinningRoot(GCHandleKind.AsyncPinned); List <Address> objectAddresses = new List <Address>(); List <PinnedObject> pinnedObjects = new List <PinnedObject>(); // Get the address of the OverlappedData and add it to the list of pinned objects. Address pinnedObjectAddress = memoryGraph.GetAddress(pinnedObjectNodeIndex); UInt16 pinnedObjectGeneration = (UInt16)heapInfo.GenerationFor(pinnedObjectAddress); objectAddresses.Add(pinnedObjectAddress); pinnedObjects.Add(new PinnedObject(pinnedObjectAddress, pinnedObjectNodeType.Name, (uint)pinnedObjectNode.Size, pinnedObjectGeneration)); // Get the buffer or list of buffers that are pinned by the asyncpinned handle. for (NodeIndex userObjectNodeIndex = pinnedObjectNode.GetFirstChildIndex(); userObjectNodeIndex != NodeIndex.Invalid; userObjectNodeIndex = pinnedObjectNode.GetNextChildIndex()) { Node userObjectNode = memoryGraph.GetNode(userObjectNodeIndex, userObjectNodeStorage); NodeType userObjectNodeType = userObjectNode.GetType(userObjectNodeTypeStorage); if (userObjectNodeType.Name.StartsWith(ByteArrayTypeName)) { // Get the address. Address bufferAddress = memoryGraph.GetAddress(userObjectNodeIndex); UInt16 bufferGeneration = (UInt16)heapInfo.GenerationFor(bufferAddress); objectAddresses.Add(bufferAddress); pinnedObjects.Add(new PinnedObject(bufferAddress, userObjectNodeType.Name, (uint)userObjectNode.Size, bufferGeneration)); } else if (userObjectNodeType.Name.StartsWith(ObjectArrayTypeName)) { for (NodeIndex arrayBufferNodeIndex = userObjectNode.GetFirstChildIndex(); arrayBufferNodeIndex != NodeIndex.Invalid; arrayBufferNodeIndex = userObjectNode.GetNextChildIndex()) { Node arrayBufferNode = memoryGraph.GetNode(arrayBufferNodeIndex, arrayBufferNodeStorage); NodeType arrayBufferNodeType = arrayBufferNode.GetType(arrayBufferNodeTypeStorage); if (arrayBufferNodeType.Name.StartsWith(ByteArrayTypeName)) { // Get the address. Address bufferAddress = memoryGraph.GetAddress(arrayBufferNodeIndex); UInt16 bufferGeneration = (UInt16)heapInfo.GenerationFor(bufferAddress); objectAddresses.Add(bufferAddress); pinnedObjects.Add(new PinnedObject(bufferAddress, arrayBufferNodeType.Name, (uint)arrayBufferNode.Size, bufferGeneration)); } } } } // Assign the list of objects into the pinned root. pinnedRoot.PinnedObjects = pinnedObjects.ToArray(); foreach (Address objectAddress in objectAddresses) { // TODO: Handle objects that are pinned multiple times (?) pinnedRoots.Add(objectAddress, pinnedRoot); } } } } } _RootTable = pinnedRoots; }
private void FindCyclesOne(int idx) { m_sccInfo[idx].m_index = index; m_sccInfo[idx].m_lowLink = index; index++; m_stack.Push(idx); m_sccInfo[idx].node = m_graph.AllocNodeStorage(); Node currentNode = m_sccInfo[idx].node; m_graph.GetNode((NodeIndex)idx, currentNode); for (NodeIndex childIdx = currentNode.GetFirstChildIndex(); childIdx != NodeIndex.Invalid; childIdx = currentNode.GetNextChildIndex()) { if (m_sccInfo[(int)childIdx].m_index == 0) { FindCyclesOne((int)childIdx); m_sccInfo[idx].m_lowLink = Math.Min(m_sccInfo[idx].m_lowLink, m_sccInfo[(int)childIdx].m_lowLink); } else if (m_stack.Contains((int)childIdx)) { m_sccInfo[idx].m_lowLink = Math.Min(m_sccInfo[idx].m_lowLink, m_sccInfo[(int)childIdx].m_index); } } if (m_sccInfo[idx].m_index == m_sccInfo[idx].m_lowLink) { bool hasCCW = false; bool hasRCW = false; int currentIdx; m_currentCycle.Clear(); NodeType type = m_graph.AllocTypeNodeStorage(); do { currentIdx = m_stack.Pop(); Node node = m_sccInfo[currentIdx].node; m_graph.GetType(node.TypeIndex, type); if (type.Name.StartsWith("[RCW")) { hasRCW = true; } else if (type.Name.StartsWith("[CCW")) { hasCCW = true; } m_currentCycle.Add(currentIdx); } while (idx != currentIdx); if (m_currentCycle.Count > 1) { m_log.WriteLine("found a cycle of {0} nodes", m_currentCycle.Count); if (hasCCW && hasRCW) { m_htmlRaw.WriteLine("<font size=\"3\" color=\"blue\">Cycle of {0} nodes<br></font>", m_currentCycle.Count); // Now print out all the nodes in this cycle. for (int i = m_currentCycle.Count - 1; i >= 0; i--) { Node nodeInCycle = m_sccInfo[m_currentCycle[i]].node; // Resetting this for printing purpose below. m_sccInfo[m_currentCycle[i]].m_index = 1; string typeName = GetPrintableString(m_graph.GetType(nodeInCycle.TypeIndex, type).Name); m_sccInfo[m_currentCycle[i]].type = typeName; m_htmlRaw.WriteLine("{0}<br>", typeName); } m_htmlRaw.WriteLine("<br><br>"); // Now print out the actual edges. Reusing the m_index field in SCCInfo. // It doesn't matter where we start, just start from the first one. startNodeIdx = m_currentCycle[m_currentCycle.Count - 1]; m_htmlRaw.WriteLine("<font size=\"3\" color=\"blue\">Paths</font><br>"); PrintEdges(startNodeIdx); } } } }