Exemple #1
0
        public void WalkTheStackAndExpandSamplesHandlesBrokenStacks(StackSourceFrameIndex kind)
        {
            // Main() calls WRONG
            const double relativeTime = 0.1;
            var          main         = new FakeStackSourceSample(
                relativeTime: relativeTime,
                name: "Main",
                frameIndex: (StackSourceFrameIndex)5,     // 5 is first non-taken enum value
                stackIndex: (StackSourceCallStackIndex)1, // 1 is first non-taken enum value
                callerIndex: StackSourceCallStackIndex.Invalid);
            var wrong = new FakeStackSourceSample(
                relativeTime: relativeTime,
                name: "WRONG",
                frameIndex: kind,
                stackIndex: (StackSourceCallStackIndex)2,
                callerIndex: main.StackIndex);

            var allSamples    = new[] { main, wrong };
            var leafs         = new[] { new Sample(wrong.StackIndex, -1, wrong.RelativeTime, wrong.Metric, -1) };
            var stackSource   = new StackSourceStub(allSamples);
            var frameNameToId = new Dictionary <string, int>();

            var frameIdToSamples = WalkTheStackAndExpandSamples(stackSource, leafs, frameNameToId, new Dictionary <int, FrameInfo>());

            Assert.Equal(0, frameNameToId[main.Name]);
            Assert.False(frameNameToId.ContainsKey(wrong.Name));

            var theOnlySample = frameIdToSamples.Single().Value.Single();

            Assert.Equal(relativeTime, theOnlySample.RelativeTime);
            Assert.Equal(0, theOnlySample.Depth);
        }
Exemple #2
0
 internal bool InUse;                                // can't be reused.  Someone is pointing at it.
 internal void CloneValue(StackInfo other)
 {
     // Note that I intentionally don't clone the StackIndex or IncPathsMatchedSoFarStorage as these are not the 'value' of this node.
     FrameIndex  = other.FrameIndex;
     CallerIndex = other.CallerIndex;
     IsOSMethod  = other.IsOSMethod;
 }
 protected override StackSourceCallStackIndex InternCallerStack(StackSourceFrameIndex frameIndex, StackSourceCallStackIndex stackIndex)
 {
     lock (internCallStackLock)
     {
         return(this.Interner.CallStackIntern(frameIndex, stackIndex));
     }
 }
        internal void StopScan(StreamscanrequestStartArgs_V1TraceData data)
        {
            // Get the requesting user process based on the PID logged inside the engine.
            TraceProcess process      = _traceLog.Processes.GetProcess(data.PID, data.TimeStampRelativeMSec);
            ProcessIndex processIndex = process.ProcessIndex;

            if (processIndex == ProcessIndex.Invalid)
            {
                return;
            }

            // Get the file scan operation.
            Dictionary <ThreadIndex, FileScanOperation> processContainer = GetOrCreateProcessContainer(processIndex);
            FileScanOperation operation = processContainer.Values.Where(s => s.File.Equals(data.Path, System.StringComparison.OrdinalIgnoreCase)).FirstOrDefault();

            if (operation != null)
            {
                operation.StopTimeRelativeMSec = data.TimeStampRelativeMSec;

                // Create the stack.
                StackSourceFrameIndex fileNodeIndex   = _stackSource.Interner.FrameIntern($"File ({operation.File})");
                StackSourceFrameIndex reasonNodeIndex = _stackSource.Interner.FrameIntern($"Reason ({(operation.Reason != null ? operation.Reason : "Unknown")})");
                StackSourceFrameIndex resultNodeIndex = _stackSource.Interner.FrameIntern($"Scan Result ({operation.Result})");
                _sample.StackIndex       = _stackSource.Interner.CallStackIntern(resultNodeIndex, operation.RequestorStack);
                _sample.StackIndex       = _stackSource.Interner.CallStackIntern(reasonNodeIndex, _sample.StackIndex);
                _sample.StackIndex       = _stackSource.Interner.CallStackIntern(fileNodeIndex, _sample.StackIndex);
                _sample.Metric           = (float)(operation.StopTimeRelativeMSec - operation.StartTimeRelativeMSec);
                _sample.TimeRelativeMSec = operation.StartTimeRelativeMSec;
                _stackSource.AddSample(_sample);
            }
        }
Exemple #5
0
 public override string GetFrameName(StackSourceFrameIndex frameIndex, bool fullModulePath)
 {
     if (frameIndex >= (StackSourceFrameIndex)base.CallFrameIndexLimit)
     {
         return(m_Interner.GetFrameName(frameIndex, fullModulePath));
     }
     return(base.GetFrameName(frameIndex, fullModulePath));
 }
Exemple #6
0
            public override string GetFrameName(StackSourceFrameIndex frameIndex, bool verboseName)
            {
                if (frameIndex >= StackSourceFrameIndex.Start)
                {
                    return((frameIndex - StackSourceFrameIndex.Start).ToString());
                }

                return(frameIndex.ToString());
            }
Exemple #7
0
        /// <summary>
        /// Implementation of StackSource protocol.
        /// </summary>
        public StackSourceModuleIndex GetModuleIndex(StackSourceFrameIndex frameIndex)
        {
            if (m_Interner.FrameStartIndex <= frameIndex)
            {
                return(m_Interner.GetModuleIndex(frameIndex));
            }

            return(StackSourceModuleIndex.Invalid);      // TODO FIX NOW this is a poor approximation
        }
Exemple #8
0
 public FakeStackSourceSample(double relativeTime, string name, StackSourceFrameIndex frameIndex,
                              StackSourceCallStackIndex stackIndex, StackSourceCallStackIndex callerIndex)
 {
     RelativeTime = relativeTime;
     Name         = name;
     FrameIndex   = frameIndex;
     StackIndex   = stackIndex;
     CallerIndex  = callerIndex;
 }
Exemple #9
0
        public StackSourceModuleIndex GetModuleIndex(StackSourceFrameIndex frameIndex)
        {
            if (frameIndex >= (StackSourceFrameIndex)base.CallFrameIndexLimit)
            {
                return(m_Interner.GetModuleIndex(frameIndex));
            }

            return(StackSourceModuleIndex.Invalid);      // TODO FIX NOW this is a poor approximation
        }
Exemple #10
0
        public SourceLocation GetSourceLine(StackSourceFrameIndex frameIndex, SymbolReader reader)
        {
            uint codeAddressIndex = (uint)frameIndex - (uint)StackSourceFrameIndex.Start;

            if (codeAddressIndex >= m_log.CodeAddresses.MaxCodeAddressIndex)
            {
                return(null);
            }
            return(m_log.CodeAddresses.GetSourceLine(reader, (CodeAddressIndex)codeAddressIndex));
        }
Exemple #11
0
        /// <summary>
        /// Given a frame index, return the cooresponding code address for it.
        /// </summary>
        public CodeAddressIndex GetFrameCodeAddress(StackSourceFrameIndex frameIndex)
        {
            uint codeAddressIndex = (uint)frameIndex - (uint)StackSourceFrameIndex.Start;

            if (codeAddressIndex >= m_log.CodeAddresses.MaxCodeAddressIndex)
            {
                return(CodeAddressIndex.Invalid);
            }
            return((CodeAddressIndex)codeAddressIndex);
        }
        /// <summary>
        /// Get the 'logcal' call stack from PROCESS ROOT (the root of all stacks) to (but not including) the frame for the
        /// thread.   By default (if you can't attribute it to anything else) it will just be attributed to the process, however
        /// it is likley that you want to insert pseudo-frames for the request and other logical groupings here.
        ///
        /// The actual method frames within a thread, as well as any resource specific pseduo-frames (e.g. BLOCKING, ...)
        /// are added by the ComputingResourceMachine itself.
        ///</summary>
        public virtual StackSourceCallStackIndex GetCallStackIndex(MutableTraceEventStackSource stackSource, TraceThread thread, TraceEvent data)
        {
            var callStackIndex = stackSource.GetCallStackForProcess(thread.Process);
            // There is no request, so add this stack as an unattributed sample.
            string frameName = "Unattributed";
            StackSourceFrameIndex requestsFrameIndex = stackSource.Interner.FrameIntern(frameName);

            callStackIndex = stackSource.Interner.CallStackIntern(requestsFrameIndex, callStackIndex);
            return(callStackIndex);
        }
Exemple #13
0
        public override string GetFrameName(StackSourceFrameIndex frameIndex, bool verboseName)
        {
            var frame = this.frames[(int)frameIndex];

            if ((int)frameIndex < this.pseudoFramesStartOffset)
            {
                return(this.eipToNameProvider.GetSymbolicName(frame.ProcessId, frame.InstructionPointer));
            }

            return(this.pseudoFrames[(int)frame.ProcessId]);
        }
Exemple #14
0
        /// <summary>
        /// Gets the name of a frame.
        /// </summary>
        /// <param name="frameIndex">The frame to look up.</param>
        /// <param name="verboseName">Whether to include full module paths.</param>
        /// <returns>The name of the frame.</returns>
        public override string GetFrameName(StackSourceFrameIndex frameIndex, bool verboseName)
        {
            Debug.Assert((int)frameIndex >= 0 && (int)frameIndex < CallFrameIndexLimit);

            int source = m_frameMap.SourceOf(frameIndex);

            Debug.Assert(source >= 0);
            var offset = m_frameMap.OffsetOf(source, frameIndex);

            return(m_sources[source].GetFrameName(offset, verboseName));
        }
        private void OnGCAllocationTick(GCAllocationTickTraceData data)
        {
            TraceThread thread = data.Thread();

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

            // Attempt to charge the allocation to a request.
            ScenarioThreadState scenarioThreadState = m_Configuration.ScenarioThreadState[(int)thread.ThreadIndex];

            CallStackIndex            traceLogCallStackIndex = data.CallStackIndex();
            StackSourceCallStackIndex callStackIndex         = scenarioThreadState.GetCallStackIndex(m_OutputStackSource, thread, data);

            // Add the thread.
            StackSourceFrameIndex threadFrameIndex = m_OutputStackSource.Interner.FrameIntern(thread.VerboseThreadName);

            callStackIndex = m_OutputStackSource.Interner.CallStackIntern(threadFrameIndex, callStackIndex);

            // Get the allocation call stack index.
            callStackIndex = m_OutputStackSource.GetCallStack(traceLogCallStackIndex, callStackIndex, null);

            // Add the type.
            string typeName = data.TypeName;

            if (typeName.Length > 0)
            {
                StackSourceFrameIndex nodeIndex = m_OutputStackSource.Interner.FrameIntern("Type " + data.TypeName);
                callStackIndex = m_OutputStackSource.Interner.CallStackIntern(nodeIndex, callStackIndex);
            }

            // Add a notification for large objects.
            if (data.AllocationKind == GCAllocationKind.Large)
            {
                StackSourceFrameIndex nodeIndex = m_OutputStackSource.Interner.FrameIntern("LargeObject");
                callStackIndex = m_OutputStackSource.Interner.CallStackIntern(nodeIndex, callStackIndex);
            }

            // Set the time.
            m_Sample.TimeRelativeMSec = data.TimeStampRelativeMSec;

            // Set the metric.
            bool seenBadAllocTick = false;

            m_Sample.Metric = data.GetAllocAmount(ref seenBadAllocTick);

            // Set the stack index.
            m_Sample.StackIndex = callStackIndex;

            // Add the sample.
            m_OutputStackSource.AddSample(m_Sample);
        }
Exemple #16
0
 public FakeStackSourceSample(bool isLastOnCallStack, double relativeTime, float metric, string name, StackSourceFrameIndex frameIndex,
                              StackSourceCallStackIndex stackIndex, StackSourceCallStackIndex callerIndex)
 {
     IsLastOnCallStack = isLastOnCallStack;
     RelativeTime      = relativeTime;
     Metric            = metric;
     Name        = name;
     FrameIndex  = frameIndex;
     StackIndex  = stackIndex;
     CallerIndex = callerIndex;
 }
Exemple #17
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);
        }
        /// <summary>
        /// Mark the thread as unblocked.
        /// </summary>
        public void LogBlockingStop(
            ComputingResourceStateMachine stateMachine,
            TraceThread thread,
            TraceEvent data)
        {
            if ((null == stateMachine) || (null == thread) || (null == data))
            {
                return;
            }

            // Only add a sample if the thread was blocked.
            if (ThreadBlocked)
            {
                StackSourceSample            sample      = stateMachine.Sample;
                MutableTraceEventStackSource stackSource = stateMachine.StackSource;

                // Set the time and metric.
                sample.TimeRelativeMSec = this.BlockTimeStartRelativeMSec;
                sample.Metric           = (float)(data.TimeStampRelativeMSec - this.BlockTimeStartRelativeMSec);

                /* Generate the stack trace. */

                CallStackIndex            traceLogCallStackIndex = data.CallStackIndex();
                ScenarioThreadState       scenarioThreadState    = stateMachine.Configuration.ScenarioThreadState[ThreadIndex];
                StackSourceCallStackIndex callStackIndex         = scenarioThreadState.GetCallStackIndex(stateMachine.StackSource, thread, data);

                // Add the thread.
                StackSourceFrameIndex threadFrameIndex = stackSource.Interner.FrameIntern(thread.VerboseThreadName);
                callStackIndex = stackSource.Interner.CallStackIntern(threadFrameIndex, callStackIndex);

                // Add the full call stack.
                callStackIndex = stackSource.GetCallStack(traceLogCallStackIndex, callStackIndex, null);

                // Add Pseud-frames representing the kind of resource.
                StackSourceFrameIndex frameIndex = stackSource.Interner.FrameIntern("BLOCKED TIME");
                callStackIndex = stackSource.Interner.CallStackIntern(frameIndex, callStackIndex);

                // Add the call stack to the sample.
                sample.StackIndex = callStackIndex;

                // Add the sample.
                stackSource.AddSample(sample);

                // Mark the thread as executing.
                BlockTimeStartRelativeMSec = -1;
            }
        }
Exemple #19
0
        public override string GetFrameName(StackSourceFrameIndex frameIndex, bool verboseName)
        {
            NodeTypeIndex typeIndex = (NodeTypeIndex)frameIndex;

            // Orphan node support
            if (typeIndex == m_graph.NodeTypeIndexLimit)
            {
                return("[not reachable from roots]");
            }

            var type       = m_graph.GetType(typeIndex, m_typeStorage);
            var moduleName = type.ModuleName;

            var ret = type.Name;

            if (moduleName != null)
            {
                if (verboseName)
                {
                    int length = moduleName.Length - 4;
                    if ((length >= 0) && (moduleName[length] == '.'))
                    {
                        moduleName = moduleName.Substring(0, length);
                    }
                }
                else
                {
                    moduleName = System.IO.Path.GetFileNameWithoutExtension(moduleName);
                }

                if (moduleName.Length == 0)
                {
                    moduleName = "?";
                }

                ret = moduleName + "!" + ShortenNameSpaces(type);
            }
            // TODO FIX NOW remove priority
            // ret +=  " " + m_typePriorities[(int)type.Index].ToString("f1");
            // TODO FIX NOW hack for CLRProfiler comparison
            // ret = Regex.Replace(ret, @" *\[\]", "[]");
            // ret = Regex.Replace(ret, @"`\d+", "");
            return(ret);
        }
Exemple #20
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);
                    }
                }
            }
        }
Exemple #21
0
        public override string GetFrameName(StackSourceFrameIndex frameIndex, bool verboseName)
        {
            if (frameIndex < StackSourceFrameIndex.Start)
            {
                return(System.Enum.GetName(typeof(StackSourceFrameIndex), frameIndex));      // TODO can be more efficient
            }
            frameIndex = (StackSourceFrameIndex)((int)frameIndex - StackSourceFrameIndex.Start);

            // a frame index might be a CLRProfiler method index, or it might be CLRProfiler nodeId index
            if ((uint)frameIndex < (uint)m_clrProfiler.MethodIdLimit)
            {
                return("!" + m_clrProfiler.GetMethodById((ProfilerMethodID)((int)frameIndex)).FullName);
            }
            else
            {
                var typeId = (ProfilerTypeID)((int)frameIndex - (int)m_clrProfiler.MethodIdLimit);
                return("ALLOC " + m_clrProfiler.GetTypeById(typeId).name);
            }
        }
Exemple #22
0
        private void AddUnkownAsyncDurationIfNeeded(StartStopActivity startStopActivity, double unknownStartTimeMSec, TraceEvent data)
        {
            Debug.Assert(0 < unknownStartTimeMSec);
            Debug.Assert(unknownStartTimeMSec <= data.TimeStampRelativeMSec);

            if (startStopActivity.IsStopped)
            {
                return;
            }

            // We dont bother with times that are too small, we consider 1msec the threshold
            double delta = data.TimeStampRelativeMSec - unknownStartTimeMSec;

            if (delta < 1)
            {
                return;
            }

            // Add a sample with the amount of unknown duration.
            var sample = new StackSourceSample(m_outputStackSource);

            sample.Metric           = (float)delta;
            sample.TimeRelativeMSec = unknownStartTimeMSec;

            StackSourceCallStackIndex stackIndex        = m_startStopActivities.GetStartStopActivityStack(m_outputStackSource, startStopActivity, data.Process());
            StackSourceFrameIndex     unknownAsyncFrame = m_outputStackSource.Interner.FrameIntern("UNKNOWN_ASYNC");

            stackIndex        = m_outputStackSource.Interner.CallStackIntern(unknownAsyncFrame, stackIndex);
            sample.StackIndex = stackIndex;

            // We can't add the samples right now because AWAIT nodes might overlap and we have to take these back.
            // The add the to this list so that they can be trimmed at that time if needed.

            List <StackSourceSample> list = m_startStopActivityToAsyncUnknownSamples.Get((int)startStopActivity.Index);

            if (list == null)
            {
                list = new List <StackSourceSample>();
                m_startStopActivityToAsyncUnknownSamples.Set((int)startStopActivity.Index, list);
            }
            list.Add(sample);
        }
        /// <summary>
        /// Log a CPU sample on this thread.
        /// </summary>
        public void LogCPUSample(
            ComputingResourceStateMachine stateMachine,
            TraceThread thread,
            TraceEvent data)
        {
            if ((null == stateMachine) || (null == thread) || (null == data))
            {
                return;
            }

            StackSourceSample sample = stateMachine.Sample;

            sample.Metric           = 1;
            sample.TimeRelativeMSec = data.TimeStampRelativeMSec;
            MutableTraceEventStackSource stackSource = stateMachine.StackSource;

            // Attempt to charge the CPU to a request.
            CallStackIndex traceLogCallStackIndex = data.CallStackIndex();

            ScenarioThreadState       scenarioThreadState = stateMachine.Configuration.ScenarioThreadState[ThreadIndex];
            StackSourceCallStackIndex callStackIndex      = scenarioThreadState.GetCallStackIndex(stackSource, thread, data);

            // Add the thread.
            StackSourceFrameIndex threadFrameIndex = stackSource.Interner.FrameIntern(thread.VerboseThreadName);

            callStackIndex = stackSource.Interner.CallStackIntern(threadFrameIndex, callStackIndex);

            // Rest of the stack.
            // NOTE: Do not pass a call stack map into this method, as it will skew results.
            callStackIndex = stackSource.GetCallStack(traceLogCallStackIndex, callStackIndex, null);

            // Add the CPU frame.
            StackSourceFrameIndex cpuFrameIndex = stackSource.Interner.FrameIntern("CPU");

            callStackIndex = stackSource.Interner.CallStackIntern(cpuFrameIndex, callStackIndex);

            // Add the sample.
            sample.StackIndex = callStackIndex;
            stackSource.AddSample(sample);
        }
Exemple #24
0
        public override string GetFrameName(StackSourceFrameIndex frameIndex, bool verboseName)
        {
            string ret = m_frames.Get((int)frameIndex);

            if (!verboseName)
            {
                var shortName = m_shortFrameNames.Get((int)frameIndex);
                if (shortName == null)
                {
                    shortName = ret;
                    // Strip off anything before the last \\ before the !
                    var exclaimIdx = ret.IndexOf('!');
                    if (0 < exclaimIdx)
                    {
                        // Becomes 0 if it fails, which is what we want.
                        var startIdx = ret.LastIndexOfAny(s_directorySeparators, exclaimIdx - 1, exclaimIdx - 1) + 1;
                        shortName = ret.Substring(startIdx);
                    }
                    m_shortFrameNames.Set((int)frameIndex, shortName);
                }
                ret = shortName;
            }
            return(ret);
        }
Exemple #25
0
            /// <summary>
            /// Gets the name of a frame.
            /// </summary>
            /// <param name="frameIndex">The frame to look up.</param>
            /// <param name="verboseName">Whether to include full module paths.</param>
            /// <returns>The name of the frame.</returns>
            public override string GetFrameName(StackSourceFrameIndex frameIndex, bool verboseName)
            {
                if (frameIndex < StackSourceFrameIndex.Start)
                {
                    switch (frameIndex)
                    {
                    case StackSourceFrameIndex.Broken:
                        return("BROKEN");

                    case StackSourceFrameIndex.Overhead:
                        return("OVERHEAD");

                    case StackSourceFrameIndex.Root:
                        return("ROOT");

                    default:
                        return("?!?");
                    }
                }
                else
                {
                    return(names[frameIndex - StackSourceFrameIndex.Start]);
                }
            }
Exemple #26
0
        /// <summary>
        /// Generates a Stack Source from an XML file created with XmlStackSourceWriter.
        /// If 'readElement' is non-null Any XML Elements that are not recognised to it so
        /// that that information can be parsed by upper level logic.  When that routine
        /// returns it must have skipped past that element (so reader points at whatever
        /// is after the End element tag).
        ///
        /// If the filename ends in .zip, the file is assumed to be a ZIPPed XML file and
        /// it is first Unziped and then processed.
        ///
        /// If the file ends in .json or .json.zip it can also read that (using JsonReaderWriterFactory.CreateJsonReader)
        /// see https://msdn.microsoft.com/en-us/library/bb412170.aspx?f=255&amp;MSPPError=-2147217396 for
        /// more on this mapping.
        /// </summary>
        public XmlStackSource(string fileName, Action <XmlReader> readElement = null)
        {
            using (Stream dataStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete))
            {
                var    xmlStream    = dataStream;
                string unzippedName = fileName;
                if (fileName.EndsWith(".zip", StringComparison.OrdinalIgnoreCase))
                {
                    var zipArchive = new ZipArchive(dataStream);
                    var entries    = zipArchive.Entries;
                    if (entries.Count != 1)
                    {
                        throw new ApplicationException("The ZIP file does not have exactly 1 XML file in it,");
                    }

                    xmlStream    = entries[0].Open();
                    unzippedName = fileName.Substring(0, fileName.Length - 4);
                }

                XmlReader reader;
                if (unzippedName.EndsWith(".json", StringComparison.OrdinalIgnoreCase))
                {
                    reader = GetJsonReader(dataStream);
                }
                else
                {
                    XmlReaderSettings settings = new XmlReaderSettings()
                    {
                        IgnoreWhitespace = true, IgnoreComments = true
                    };
                    reader = XmlTextReader.Create(xmlStream, settings);
                }

                reader.Read();      // Skip the StackWindow element.
                bool readStackSource = false;
                for (; ;)
                {
                    if (reader.NodeType == XmlNodeType.Element)
                    {
                        if (reader.Name == "StackSource")
                        {
                            if (!readStackSource)
                            {
                                Read(reader);
                                readStackSource = true;
                            }
                        }
                        else if (readElement != null)
                        {
                            readElement(reader);
                        }
                        else
                        {
                            reader.Read();
                        }
                    }
                    else if (!reader.Read())
                    {
                        break;
                    }
                }
                if (m_interner != null)
                {
                    // Transfer the interned names to the m_frames array.
                    // Go from high to low so at most one reallocation happens.
                    for (int i = m_interner.FrameCount - 1; 0 <= i; --i)
                    {
                        StackSourceFrameIndex frameIdx = m_interner.FrameStartIndex + i;
                        m_frames.Set((int)frameIdx, m_interner.GetFrameName(frameIdx, true));
                    }

                    for (int i = m_interner.CallStackCount - 1; 0 <= i; --i)
                    {
                        StackSourceCallStackIndex stackIdx = m_interner.CallStackStartIndex + i;
                        m_stacks.Set((int)stackIdx, new Frame(
                                         (int)m_interner.GetFrameIndex(stackIdx),
                                         (int)m_interner.GetCallerIndex(stackIdx)));
                    }

                    m_interner = null;  // we are done with it.
                }
            }
        }
 protected virtual StackSourceCallStackIndex InternCallerStack(StackSourceFrameIndex frameIndex, StackSourceCallStackIndex stackIndex)
 {
     return(this.Interner.CallStackIntern(frameIndex, stackIndex));
 }
Exemple #28
0
        /// <summary>
        /// Generate the thread time stacks, outputting to 'stackSource'.
        /// </summary>
        /// <param name="outputStackSource"></param>
        /// <param name="traceEvents">Optional filtered trace events.</param>
        public void GenerateThreadTimeStacks(MutableTraceEventStackSource outputStackSource, TraceEvents traceEvents = null)
        {
            m_outputStackSource   = outputStackSource;
            m_sample              = new StackSourceSample(outputStackSource);
            m_nodeNameInternTable = new Dictionary <double, StackSourceFrameIndex>(10);
            m_ExternalFrameIndex  = outputStackSource.Interner.FrameIntern("UNMANAGED_CODE_TIME");
            m_cpuFrameIndex       = outputStackSource.Interner.FrameIntern("CPU_TIME");

            TraceLogEventSource eventSource = traceEvents == null?m_eventLog.Events.GetSource() :
                                                  traceEvents.GetSource();

            if (GroupByStartStopActivity)
            {
                UseTasks = true;
            }

            if (UseTasks)
            {
                m_activityComputer = new ActivityComputer(eventSource, m_symbolReader);
                m_activityComputer.AwaitUnblocks += delegate(TraceActivity activity, TraceEvent data)
                {
                    var sample = m_sample;
                    sample.Metric           = (float)(activity.StartTimeRelativeMSec - activity.CreationTimeRelativeMSec);
                    sample.TimeRelativeMSec = activity.CreationTimeRelativeMSec;

                    // The stack at the Unblock, is the stack at the time the task was created (when blocking started).
                    sample.StackIndex = m_activityComputer.GetCallStackForActivity(m_outputStackSource, activity, GetTopFramesForActivityComputerCase(data, data.Thread(), true));

                    StackSourceFrameIndex awaitFrame = m_outputStackSource.Interner.FrameIntern("AWAIT_TIME");
                    sample.StackIndex = m_outputStackSource.Interner.CallStackIntern(awaitFrame, sample.StackIndex);

                    m_outputStackSource.AddSample(sample);

                    if (m_threadToStartStopActivity != null)
                    {
                        UpdateStartStopActivityOnAwaitComplete(activity, data);
                    }
                };

                // We can provide a bit of extra value (and it is useful for debugging) if we immediately log a CPU
                // sample when we schedule or start a task.  That we we get the very instant it starts.
                var tplProvider = new TplEtwProviderTraceEventParser(eventSource);
                tplProvider.AwaitTaskContinuationScheduledSend += OnSampledProfile;
                tplProvider.TaskScheduledSend += OnSampledProfile;
                tplProvider.TaskExecuteStart  += OnSampledProfile;
                tplProvider.TaskWaitSend      += OnSampledProfile;
                tplProvider.TaskWaitStop      += OnTaskUnblock; // Log the activity stack even if you don't have a stack.
            }

            if (GroupByStartStopActivity)
            {
                m_startStopActivities = new StartStopActivityComputer(eventSource, m_activityComputer, IgnoreApplicationInsightsRequestsWithRelatedActivityId);

                // Maps thread Indexes to the start-stop activity that they are executing.
                m_threadToStartStopActivity = new StartStopActivity[m_eventLog.Threads.Count];

                /*********  Start Unknown Async State machine for StartStop activities ******/
                // The delegates below along with the AddUnkownAsyncDurationIfNeeded have one purpose:
                // To inject UNKNOWN_ASYNC stacks when there is an active start-stop activity that is
                // 'missing' time.   It has the effect of insuring that Start-Stop tasks always have
                // a metric that is not unrealistically small.
                m_activityComputer.Start += delegate(TraceActivity activity, TraceEvent data)
                {
                    StartStopActivity newStartStopActivityForThread = m_startStopActivities.GetCurrentStartStopActivity(activity.Thread, data);
                    UpdateThreadToWorkOnStartStopActivity(activity.Thread, newStartStopActivityForThread, data);
                };

                m_activityComputer.AfterStop += delegate(TraceActivity activity, TraceEvent data, TraceThread thread)
                {
                    StartStopActivity newStartStopActivityForThread = m_startStopActivities.GetCurrentStartStopActivity(thread, data);
                    UpdateThreadToWorkOnStartStopActivity(thread, newStartStopActivityForThread, data);
                };

                m_startStopActivities.Start += delegate(StartStopActivity startStopActivity, TraceEvent data)
                {
                    // We only care about the top-most activities since unknown async time is defined as time
                    // where a top  most activity is running but no thread (or await time) is associated with it
                    // fast out otherwise (we just insure that we mark the thread as doing this activity)
                    if (startStopActivity.Creator != null)
                    {
                        UpdateThreadToWorkOnStartStopActivity(data.Thread(), startStopActivity, data);
                        return;
                    }

                    // Then we have a refcount of exactly one
                    Debug.Assert(m_unknownTimeStartMsec.Get((int)startStopActivity.Index) >= 0); // There was nothing running before.

                    m_unknownTimeStartMsec.Set((int)startStopActivity.Index, -1);                // Set it so just we are running.
                    m_threadToStartStopActivity[(int)data.Thread().ThreadIndex] = startStopActivity;
                };

                m_startStopActivities.Stop += delegate(StartStopActivity startStopActivity, TraceEvent data)
                {
                    // We only care about the top-most activities since unknown async time is defined as time
                    // where a top  most activity is running but no thread (or await time) is associated with it
                    // fast out otherwise
                    if (startStopActivity.Creator != null)
                    {
                        return;
                    }

                    double unknownStartTime = m_unknownTimeStartMsec.Get((int)startStopActivity.Index);
                    if (0 < unknownStartTime)
                    {
                        AddUnkownAsyncDurationIfNeeded(startStopActivity, unknownStartTime, data);
                    }

                    // Actually emit all the async unknown events.
                    List <StackSourceSample> samples = m_startStopActivityToAsyncUnknownSamples.Get((int)startStopActivity.Index);
                    if (samples != null)
                    {
                        foreach (var sample in samples)
                        {
                            m_outputStackSource.AddSample(sample);  // Adding Unknown ASync
                        }

                        m_startStopActivityToAsyncUnknownSamples.Set((int)startStopActivity.Index, null);
                    }

                    m_unknownTimeStartMsec.Set((int)startStopActivity.Index, 0);
                    Debug.Assert(m_threadToStartStopActivity[(int)data.Thread().ThreadIndex] == startStopActivity ||
                                 m_threadToStartStopActivity[(int)data.Thread().ThreadIndex] == null);
                    m_threadToStartStopActivity[(int)data.Thread().ThreadIndex] = null;
                };
            }

            eventSource.Clr.GCAllocationTick          += OnSampledProfile;
            eventSource.Clr.GCSampledObjectAllocation += OnSampledProfile;

            var eventPipeTraceEventPraser = new SampleProfilerTraceEventParser(eventSource);

            eventPipeTraceEventPraser.ThreadSample += OnSampledProfile;

            if (IncludeEventSourceEvents)
            {
                eventSource.Dynamic.All += delegate(TraceEvent data)
                {
                    // TODO decide what the correct heuristic is.
                    // Currently I only do this for things that might be an EventSoruce (uses the name->Guid hashing)
                    // Most importantly, it excludes the high volume CLR providers.
                    if (!TraceEventProviders.MaybeAnEventSource(data.ProviderGuid))
                    {
                        return;
                    }

                    //  We don't want most of the FrameworkEventSource events either.
                    if (data.ProviderGuid == FrameworkEventSourceTraceEventParser.ProviderGuid)
                    {
                        if (!((TraceEventID)140 <= data.ID && data.ID <= (TraceEventID)143))    // These are the GetResponce and GetResestStream events
                        {
                            return;
                        }
                    }

                    // We don't care about EventPipe sample profiler events.
                    if (data.ProviderGuid == SampleProfilerTraceEventParser.ProviderGuid)
                    {
                        return;
                    }

                    // We don't care about the TPL provider.  Too many events.
                    if (data.ProviderGuid == TplEtwProviderTraceEventParser.ProviderGuid)
                    {
                        return;
                    }

                    // We don't care about ManifestData events.
                    if (data.ID == (TraceEventID)0xFFFE)
                    {
                        return;
                    }

                    TraceThread thread = data.Thread();
                    if (thread == null)
                    {
                        return;
                    }

                    StackSourceCallStackIndex stackIndex = GetCallStack(data, thread);

                    // Tack on additional info about the event.
                    var fieldNames = data.PayloadNames;
                    for (int i = 0; i < fieldNames.Length; i++)
                    {
                        var fieldName      = fieldNames[i];
                        var value          = data.PayloadString(i);
                        var fieldNodeName  = "EventData: " + fieldName + "=" + value;
                        var fieldNodeIndex = m_outputStackSource.Interner.FrameIntern(fieldNodeName);
                        stackIndex = m_outputStackSource.Interner.CallStackIntern(fieldNodeIndex, stackIndex);
                    }
                    stackIndex = m_outputStackSource.Interner.CallStackIntern(m_outputStackSource.Interner.FrameIntern("EventName: " + data.ProviderName + "/" + data.EventName), stackIndex);

                    m_threadState[(int)thread.ThreadIndex].LogThreadStack(data.TimeStampRelativeMSec, stackIndex, thread, this, false);
                };
            }

            eventSource.Process();

            m_outputStackSource.DoneAddingSamples();
            m_threadState = null;
        }
Exemple #29
0
 public abstract ValueTask <SourceLocation> GetSourceLocation(StackSourceFrameIndex frameIndex);
Exemple #30
0
    /// <summary>
    /// If you place a file called PerfViewExtensions\PerfViewStartup next to the PerfView.exe it will
    /// run execute commands in that file.  If you put
    ///
    /// DeclareFileView .etl "Demo View In Etl File" DemoDeclareFileView
    ///
    /// It will create a child node for all .etl files called 'Demo View In Etl File'  If you click
    /// on this node it will execute this user command.  It is passed the name of the file that was
    /// opened and the name of the view that was opened (in this case 'Demo View In Etl File').
    /// </summary>
    public void DemoDeclareFileView(string fileName, string viewName)
    {
        // This demo creates a view that shows you all the START events in a stack view.
        LogFile.WriteLine("************ In DemoDeclareFileView file = {0} view = {1}", fileName, viewName);

        // This is an example of opening an ETL file.
        ETLDataFile etlFile = OpenETLFile(fileName);

        // An ETLData file is a high level construct that knows about high level 'views' of the data (CPU stacks, thread time Stacks ...)

        // However if you want to create a new view, you probably want a TraceLog which is the underlying ETW data.
        TraceLog traceLog = etlFile.TraceLog;

        // A tracelog represent the whole ETL file (which has process, images, threads etc), we want events, and we want callbacks
        // for each event which is what GetSource() does.   THus we get a source (which we can add callbacks to)
        var eventSource = traceLog.Events.GetSource();

        // At this point create the 'output' of our routine.  Our goal is to produce stacks that we will view in the
        // stack viewer.   Thus we create an 'empty' one fo these.
        var stackSource = new MutableTraceEventStackSource(traceLog);
        // A stack source is  list of samples.  We create a sample structure, mutate it and then call AddSample() repeatedly to add samples.
        var sample = new StackSourceSample(stackSource);

        // Setup the callbacks, In this case we are going to watch for stacks where GCs happen
        eventSource.Clr.GCStart += delegate(GCStartTraceData data)
        {
            // An TraceLog should have a callstack associated with this event;
            CallStackIndex callStackIdx = data.CallStackIndex();
            if (callStackIdx != CallStackIndex.Invalid)
            {
                // Convert the TraceLog call stack to a MutableTraceEventStackSource call stack
                StackSourceCallStackIndex stackCallStackIndex = stackSource.GetCallStack(callStackIdx, data);

                // Add a pseudo frame on the bottom of the stack
                StackSourceFrameIndex frameIdxForName = stackSource.Interner.FrameIntern("GC Gen " + data.Depth + "Reason " + data.Reason);
                stackCallStackIndex = stackSource.Interner.CallStackIntern(frameIdxForName, stackCallStackIndex);

                // create a sample with that stack and add it to the stack source (list of samples)
                sample.Metric           = 1;
                sample.TimeRelativeMSec = data.TimeStampRelativeMSec;
                sample.StackIndex       = stackCallStackIndex;
                stackSource.AddSample(sample);
            }
        };
        // You can set up other callback for other events.

        // This causes the TraceLog source to actually spin through all the events calling our callbacks as requested.
        eventSource.Process();

        // We are done adding sample to our stack Source, so we tell the MutableTraceEventStackSource that.
        // after that is becomes viewable (and read-only).
        stackSource.DoneAddingSamples();

        // Take the stack source (raw data) and make it into a 'Stacks' allows you to add filtering to and send to 'OpendStackViewer'
        Stacks stacksForViewer = new Stacks(stackSource, viewName, etlFile);

        // Set any filtering options here.

        // Now we can display the viewer.
        OpenStackViewer(stacksForViewer);
    }