Beispiel #1
0
        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"
                };
            }
Beispiel #3
0
        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;
        }
Beispiel #4
0
        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);
                    }
                }
            }
        }