Ejemplo n.º 1
0
        /// <summary>
        /// Add a sample representing the pinned object allocation.
        /// </summary>
        private void WriteAllocationStack(
            Address objectAddress,
            PinningRoot pinnedRoot,
            PinningStackAnalysisObject liveObjectInfo)
        {
            // Get the pinned object from the pinned root.
            PinnedObject pinnedObject = null;

            foreach (PinnedObject o in pinnedRoot.PinnedObjects)
            {
                if (o.ObjectAddress == objectAddress)
                {
                    pinnedObject = o;
                    break;
                }
            }

            // This should not happen, but we put this here to ensure that we don't crash.
            if (null == pinnedObject)
            {
                System.Diagnostics.Debug.Assert(false, "Pinned object could not be found, but was found in the _RootTable.");
                return;
            }

            // Get the allocation call stack.
            StackSourceCallStackIndex rootCallStackIndex = liveObjectInfo.AllocStack;

            // Add the generation pseudo-node.
            string generationString = "GENERATION " + pinnedObject.Generation;
            StackSourceFrameIndex     generationFrameIndex = _StackSource.Interner.FrameIntern(generationString);
            StackSourceCallStackIndex callStackIndex       = _StackSource.Interner.CallStackIntern(generationFrameIndex, rootCallStackIndex);

            // Add the type of the object.
            string objectTypeString = "OBJECT_TYPE " + pinnedObject.ObjectType;
            StackSourceFrameIndex objectTypeFrameIndex = _StackSource.Interner.FrameIntern(objectTypeString);

            callStackIndex = _StackSource.Interner.CallStackIntern(objectTypeFrameIndex, callStackIndex);

            // Set the object instance.
            string objectInstanceString = "OBJECT_INSTANCE " + pinnedObject.ObjectAddress;
            StackSourceFrameIndex objectInstanceFrameIndex = _StackSource.Interner.FrameIntern(objectInstanceString);

            callStackIndex = _StackSource.Interner.CallStackIntern(objectInstanceFrameIndex, callStackIndex);

            // Setup the sample.
            _Sample.TimeRelativeMSec = liveObjectInfo.AllocationTimeRelativeMSec;
            _Sample.Metric           = pinnedObject.ObjectSize;
            _Sample.StackIndex       = callStackIndex;
            _StackSource.AddSample(_Sample);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Write out a sample for each pin operation of the input object.
        /// </summary>
        private void WritePinningStacks(
            Address objectAddress,
            PinningRoot pinnedRoot,
            PinningStackAnalysisObject liveObjectInfo)
        {
            if (liveObjectInfo.PinInfo != null)
            {
                foreach (PinningStackAnalysisPinInfo pinInfo in liveObjectInfo.PinInfo)
                {
                    // Get the pinning stack and the time.

                    foreach (PinnedObject pinnedObject in pinnedRoot.PinnedObjects)
                    {
                        // Add the generation pseudo-node.
                        string generationString = "GENERATION " + pinnedObject.Generation;
                        StackSourceFrameIndex     generationFrameIndex = _StackSource.Interner.FrameIntern(generationString);
                        StackSourceCallStackIndex callStackIndex       = _StackSource.Interner.CallStackIntern(generationFrameIndex, pinInfo.PinStack);

                        // Add the root type.
                        string rootTypeString = "ROOT_TYPE " + pinnedRoot.RootType.ToString();
                        StackSourceFrameIndex rootTypeFrameIndex = _StackSource.Interner.FrameIntern(rootTypeString);
                        callStackIndex = _StackSource.Interner.CallStackIntern(rootTypeFrameIndex, callStackIndex);

                        // Add the type of the object.
                        string objectTypeString = "OBJECT_TYPE " + pinnedObject.ObjectType;
                        StackSourceFrameIndex objectTypeFrameIndex = _StackSource.Interner.FrameIntern(objectTypeString);
                        callStackIndex = _StackSource.Interner.CallStackIntern(objectTypeFrameIndex, callStackIndex);

                        // Set the object instance.
                        string objectInstanceString = "OBJECT_INSTANCE " + pinnedObject.ObjectAddress;
                        StackSourceFrameIndex objectInstanceFrameIndex = _StackSource.Interner.FrameIntern(objectInstanceString);
                        callStackIndex = _StackSource.Interner.CallStackIntern(objectInstanceFrameIndex, callStackIndex);

                        // Set the metric to 1 since the metric represents the number of pin operations.
                        _Sample.Metric = 1;

                        // Set the call stack.
                        _Sample.TimeRelativeMSec = pinInfo.PinTimeRelativeMSec;
                        _Sample.StackIndex       = callStackIndex;
                        _StackSource.AddSample(_Sample);
                    }
                }
            }
        }
Ejemplo n.º 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;
        }