private void VisitNode(MemoryNode currentNode)
        {
            MemoryNode oldMemNode = currentNode;

            // Get the generation for the current node.
            int generation = _HeapInfo.GenerationFor(oldMemNode.Address);

            // Create a MemoryNodeBuilder for the new graph that represents the current node
            // unless the current node is the root, as we've already created one.
            MemoryNodeBuilder newMemNodeBuilder = null;

            if (currentNode.Index == _OriginalMemoryGraph.RootIndex)
            {
                newMemNodeBuilder = _RootNode;
            }
            else
            {
                // Get the parent node.
                MemoryNodeBuilder parentMemNodeBuilder = null;
                if ((oldMemNode.Address != 0) && (generation > _GenerationToCondemn))
                {
                    if (generation == 1)
                    {
                        parentMemNodeBuilder = _Gen1RootNode;
                    }
                    else
                    {
                        parentMemNodeBuilder = _Gen2RootNode;
                    }
                }
                else
                {
                    parentMemNodeBuilder = _OldNodeToNewParentMap[(int)currentNode.Index];
                }

                if (parentMemNodeBuilder == null)
                {
                    parentMemNodeBuilder = _UnknownRootNode;
                }

                // Get the current node's type and object address.
                NodeType nodeType = _OriginalMemoryGraph.GetType(oldMemNode.TypeIndex, _OldNodeTypeStorage);

                // Create the new generation aware type name.
                string typeName = null;
                if (oldMemNode.Address != 0 && generation >= 0)
                {
                    if (generation == 3)
                    {
                        typeName = string.Format("LOH: {0}", nodeType.Name);
                    }
                    else
                    {
                        typeName = string.Format("Gen{0}: {1}", generation, nodeType.Name);
                    }
                }
                else
                {
                    if (oldMemNode.Address != 0)
                    {
                        _Log.WriteLine(string.Format("Generation: {0}; Address: {1}; Type: {2}", generation, oldMemNode.Address, nodeType.Name));
                    }
                    typeName = nodeType.Name;
                }

                // Create the new node.
                if (ShouldAddToGraph(oldMemNode, nodeType))
                {
                    if (oldMemNode.Address == 0)
                    {
                        newMemNodeBuilder = parentMemNodeBuilder.FindOrCreateChild(typeName);
                    }
                    else
                    {
                        NodeIndex newNodeIndex = _NewMemoryGraph.GetNodeIndex(oldMemNode.Address);
                        newMemNodeBuilder = new MemoryNodeBuilder(_NewMemoryGraph, typeName, null, newNodeIndex);

                        parentMemNodeBuilder.AddChild(newMemNodeBuilder);

                        // Set the object size.
                        if (generation <= _GenerationToCondemn)
                        {
                            newMemNodeBuilder.Size = oldMemNode.Size;
                        }
                        else
                        {
                            _Log.WriteLine("Ignoring Object Size: " + typeName);
                        }
                    }
                }
            }

            // Associate all children of the current node with this object's new MemoryNodeBuilder.
            for (NodeIndex childIndex = oldMemNode.GetFirstChildIndex(); childIndex != NodeIndex.Invalid; childIndex = oldMemNode.GetNextChildIndex())
            {
                _OldNodeToNewParentMap[(int)childIndex] = newMemNodeBuilder;
            }
        }
示例#2
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;
        }