예제 #1
0
        private void OnSetGCHandle(SetGCHandleTraceData data)
        {
            if (ProcessId != data.ProcessID)
            {
                return;
            }

            // This is not a pinned handle.
            if ((GCHandleKind.AsyncPinned != data.Kind) && (GCHandleKind.Pinned != data.Kind))
            {
                return;
            }

            PinningStackAnalysisObject objectInfo = GetPinningInfo(data.ObjectID);

            Debug.Assert(objectInfo != null);
            if (objectInfo == null)
            {
                return;
            }

            // TODO FIX NOW worry about duplicates between the public and private CLR providers.

            if (objectInfo.PinInfo == null)
            {
                objectInfo.PinInfo = new List <PinningStackAnalysisPinInfo>();
            }

            var stackIndex = StackSource.GetCallStack(data.CallStackIndex(), data);

            objectInfo.PinInfo.Add(new PinningStackAnalysisPinInfo(data.TimeStampRelativeMSec, stackIndex, data.Kind));
        }
예제 #2
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);
        }
예제 #3
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);
                    }
                }
            }
        }
예제 #4
0
        /// <summary>
        /// Execute the pinned object analyzer.
        /// </summary>
        internal void Execute(
            GCPinnedObjectViewType viewType)
        {
            // Process the heap snapshot, and populate the root table and process id.
            ProcessHeapSnapshot();

            // Instantiate the necessary trace event parsers.
            TraceEventDispatcher     eventDispatcher = _TraceLog.Events.GetSource();
            PerfViewTraceEventParser perfViewParser  = new PerfViewTraceEventParser(eventDispatcher);

            // we want the state of the heap at the time the snapshot was taken.
            perfViewParser.TriggerHeapSnapshot += delegate(TriggerHeapSnapshotTraceData data)
            {
                eventDispatcher.StopProcessing();
            };

            var heapWithPinningInfo = new PinningStackAnalysis(eventDispatcher, _TraceLog.Processes.GetProcess(_ProcessID, _TraceLog.SessionDuration.TotalMilliseconds), _StackSource, _Log);

            // Process the ETL file up until we detect that the heap snapshot was taken.
            eventDispatcher.Process();

            // Iterate through all pinned objects in the heap snapshot.
            foreach (KeyValuePair <Address, PinningRoot> pinnedPair in _RootTable)
            {
                // Try to match the object in the heap snapshot with an object in the ETL.
                PinningStackAnalysisObject liveObjectInfo = heapWithPinningInfo.GetPinningInfo(pinnedPair.Key);
                if (liveObjectInfo != null)
                {
                    // Found a match, write the appropriate call stacks.
                    if (viewType == GCPinnedObjectViewType.PinnedObjectAllocations)
                    {
                        WriteAllocationStack(pinnedPair.Key, pinnedPair.Value, liveObjectInfo);
                    }
                    else if (viewType == GCPinnedObjectViewType.PinnedHandles)
                    {
                        WritePinningStacks(pinnedPair.Key, pinnedPair.Value, liveObjectInfo);
                    }
                }
            }
        }