예제 #1
0
        /// <summary>
        /// Unwind the wrapped sources to get to a TraceEventStackSource if possible.
        /// </summary>
        private static TraceEventStackSource GetTraceEventStackSource(StackSource source)
        {
            StackSourceStacks     rawSource = source;
            TraceEventStackSource asTraceEventStackSource = null;

            for (; ;)
            {
                asTraceEventStackSource = rawSource as TraceEventStackSource;
                if (asTraceEventStackSource != null)
                {
                    return(asTraceEventStackSource);
                }

                var asCopyStackSource = rawSource as CopyStackSource;
                if (asCopyStackSource != null)
                {
                    rawSource = asCopyStackSource.SourceStacks;
                    continue;
                }
                var asStackSource = rawSource as StackSource;
                if (asStackSource != null && asStackSource != asStackSource.BaseStackSource)
                {
                    rawSource = asStackSource.BaseStackSource;
                    continue;
                }
                return(null);
            }
        }
예제 #2
0
            private (string etlx, Dictionary <string, ETWHelper.CallTreeItem> callTree) TryGetCallTree(int pid)
            {
                string maybeEtlx = null;

                try
                {
                    var(tlog, etlx) = ETWHelper.GetTraceLog(outFile);
                    maybeEtlx       = etlx;
                    using (tlog)
                    {
                        var proc     = tlog.Processes.FirstOrDefault(p => p.ProcessID == pid);
                        var stacks   = new TraceEventStackSource(proc.EventsInProcess.Filter(t => t is SampledProfileTraceData));
                        var callTree = ETWHelper.GetCallTree(stacks, out var timeModifier);
                        //if (GetAllResultFiles(outFile) is var allFiles && allFiles.Length > 1)
                        //{
                        //    string tempName = Path.ChangeExtension(outFile, ".etl.new");
                        //    TraceEventSession.Merge(allFiles, tempName);
                        //    // Delete the originals.
                        //    foreach (var mergeInput in allFiles)
                        //        File.Delete(mergeInput);
                        //    // Place the output in its final resting place.
                        //    File.Move(tempName, outFile);
                        //}
                        return(etlx, callTree);
                    }
                }
                catch (Exception ex)
                {
                    return(maybeEtlx, new Dictionary <string, ETWHelper.CallTreeItem>());
                }
            }
예제 #3
0
        private void LookupWarmNGENSymbols()
        {
            TraceEventStackSource asTraceEventStackSource = GetTraceEventStackSource(_rawStackSource);

            if (asTraceEventStackSource == null)
            {
                return;
            }

            SymbolReaderOptions savedOptions = _symbolReader.Options;

            try
            {
                // NGEN PDBs (even those not yet produced) are considered to be in the cache.
                _symbolReader.Options = SymbolReaderOptions.CacheOnly;

                // Resolve all NGEN images.
                asTraceEventStackSource.LookupWarmSymbols(1, _symbolReader, _rawStackSource, s => s.Name.EndsWith(".ni", StringComparison.OrdinalIgnoreCase));

                // Invalidate cached data structures to finish resolving symbols.
                InvalidateCachedStructures();
            }
            finally
            {
                _symbolReader.Options = savedOptions;
            }
        }
예제 #4
0
        public static StackSource CPUStacks(this TraceLog eventLog, TraceProcess process = null, bool showUnknownAddresses = false, Predicate <TraceEvent> predicate = null)
        {
            TraceEvents events = process == null?eventLog.Events.Filter(x => (predicate == null || predicate(x)) && x is SampledProfileTraceData && x.ProcessID != 0) : process.EventsInProcess.Filter(x => (predicate == null || predicate(x)) && x is SampledProfileTraceData);

            var traceStackSource = new TraceEventStackSource(events)
            {
                ShowUnknownAddresses = showUnknownAddresses
            };

            return(traceStackSource);
        }
예제 #5
0
        public static StackSource CPUStacks(this TraceLog eventLog, TraceProcess process = null, Predicate <TraceEvent> predicate = null)
        {
            TraceEvents events;

            if (process == null)
            {
                events = eventLog.Events.Filter((x) => ((predicate == null) || predicate(x)) && x is SampledProfileTraceData && x.ProcessID != 0);
            }
            else
            {
                events = process.EventsInProcess.Filter((x) => ((predicate == null) || predicate(x)) && x is SampledProfileTraceData);
            }

            var traceStackSource = new TraceEventStackSource(events);

            // We clone the samples so that we don't have to go back to the ETL file from here on.
            return(CopyStackSource.Clone(traceStackSource));
        }
        public static StackSource SingleEventTypeStack(this TraceEvents events, TraceProcess process = null, Predicate <TraceEvent> predicate = null)
        {
            // optimization only
            if (process != null)
            {
                var start = Math.Max(events.StartTimeRelativeMSec, process.StartTimeRelativeMsec);
                var end   = Math.Min(events.EndTimeRelativeMSec, process.EndTimeRelativeMsec);
                events = events.FilterByTime(start, end);
                events = events.Filter(x => (predicate == null || predicate(x)) && x.ProcessID == process.ProcessID);
            }
            else
            {
                events = events.Filter(x => (predicate == null || predicate(x)) && x.ProcessID != 0); // TODO: Is it really correc that x.ProcessID != 0 should be there? What if we want see these?
            }

            var traceStackSource = new TraceEventStackSource(events)
            {
                ShowUnknownAddresses = true
            };

            return(CopyStackSource.Clone(traceStackSource));
        }
예제 #7
0
        public static StackSource CPUStacks(
            this Microsoft.Diagnostics.Tracing.Etlx.TraceLog eventLog,
            Microsoft.Diagnostics.Tracing.Etlx.TraceProcess process = null,
            Predicate <TraceEvent> predicate = null)
        {
            Microsoft.Diagnostics.Tracing.Etlx.TraceEvents events;

            if (process == null)
            {
                events = eventLog.Events.Filter((x) => ((predicate == null) || predicate(x)) && x is SampledProfileTraceData && x.ProcessID != 0);
            }
            else
            {
                events = process.EventsInProcess.Filter((x) => ((predicate == null) || predicate(x)) && x is SampledProfileTraceData);
            }

            var traceStackSource = new TraceEventStackSource(events);

            traceStackSource.ShowUnknownAddresses = true;

            // Clone the samples so that the caller doesn't have to go back to the ETL file from here on.
            return(CopyStackSource.Clone(traceStackSource));
        }
예제 #8
0
        private SourceLocation GetSourceLocation(CallTreeNodeBase asCallTreeNodeBase, string cellText, out SortedDictionary <int, float> metricOnLine)
        {
            metricOnLine = null;
            var m = Regex.Match(cellText, "<<(.*!.*)>>");

            if (m.Success)
            {
                cellText = m.Groups[1].Value;
            }

            var frameIndexCounts = new Dictionary <StackSourceFrameIndex, float>();

            asCallTreeNodeBase.GetSamples(false, delegate(StackSourceSampleIndex sampleIdx)
            {
                var matchingFrameIndex = StackSourceFrameIndex.Invalid;
                var sample             = this.stacksource.GetSampleByIndex(sampleIdx);
                var callStackIdx       = sample.StackIndex;
                while (callStackIdx != StackSourceCallStackIndex.Invalid)
                {
                    var frameIndex = this.stacksource.GetFrameIndex(callStackIdx);
                    var frameName  = this.stacksource.GetFrameName(frameIndex, false);
                    if (frameName == cellText)
                    {
                        matchingFrameIndex = frameIndex;        // We keep overwriting it, so we get the entry closest to the root.
                    }
                    callStackIdx = this.stacksource.GetCallerIndex(callStackIdx);
                }
                if (matchingFrameIndex != StackSourceFrameIndex.Invalid)
                {
                    float count = 0;
                    frameIndexCounts.TryGetValue(matchingFrameIndex, out count);
                    frameIndexCounts[matchingFrameIndex] = count + sample.Metric;
                }
                return(true);
            });

            var   maxFrameIdx      = StackSourceFrameIndex.Invalid;
            float maxFrameIdxCount = -1;

            foreach (var keyValue in frameIndexCounts)
            {
                if (keyValue.Value >= maxFrameIdxCount)
                {
                    maxFrameIdxCount = keyValue.Value;
                    maxFrameIdx      = keyValue.Key;
                }
            }

            if (maxFrameIdx == StackSourceFrameIndex.Invalid)
            {
                return(null);
            }

            // Find the most primitive TraceEventStackSource
            TraceEventStackSource asTraceEventStackSource = GetTraceEventStackSource(this.stacksource);

            if (asTraceEventStackSource == null)
            {
                return(null);
            }

            var frameToLine = new Dictionary <StackSourceFrameIndex, int>();

            var sourceLocation = asTraceEventStackSource.GetSourceLine(maxFrameIdx, this.reader);

            if (sourceLocation != null)
            {
                var filePathForMax = sourceLocation.SourceFile.BuildTimeFilePath;
                metricOnLine = new SortedDictionary <int, float>();

                // Accumulate the counts on a line basis
                foreach (StackSourceFrameIndex frameIdx in frameIndexCounts.Keys)
                {
                    var loc = asTraceEventStackSource.GetSourceLine(frameIdx, this.reader);
                    if (loc != null && loc.SourceFile.BuildTimeFilePath == filePathForMax)
                    {
                        frameToLine[frameIdx] = loc.LineNumber;
                        float metric;
                        metricOnLine.TryGetValue(loc.LineNumber, out metric);
                        metric += frameIndexCounts[frameIdx];
                        metricOnLine[loc.LineNumber] = metric;
                    }
                }
            }

            bool        commonMethodIdxSet = false;
            MethodIndex commonMethodIdx    = MethodIndex.Invalid;

            var nativeAddressFreq = new SortedDictionary <ulong, Tuple <int, float> >();

            foreach (var keyValue in frameIndexCounts)
            {
                var codeAddr = asTraceEventStackSource.GetFrameCodeAddress(keyValue.Key);
                if (codeAddr != CodeAddressIndex.Invalid)
                {
                    var methodIdx = asTraceEventStackSource.TraceLog.CodeAddresses.MethodIndex(codeAddr);
                    if (methodIdx != MethodIndex.Invalid)
                    {
                        if (!commonMethodIdxSet)
                        {
                            commonMethodIdx = methodIdx;            // First time, set it as the common method.
                        }
                        else if (methodIdx != commonMethodIdx)
                        {
                            methodIdx = MethodIndex.Invalid;        // More than one method, give up.
                        }
                        commonMethodIdxSet = true;
                    }

                    var nativeAddr = asTraceEventStackSource.TraceLog.CodeAddresses.Address(codeAddr);
                    var lineNum    = 0;
                    frameToLine.TryGetValue(keyValue.Key, out lineNum);
                    nativeAddressFreq[nativeAddr] = new Tuple <int, float>(lineNum, keyValue.Value);
                }
            }

            foreach (var keyValue in nativeAddressFreq)
            {
                Console.WriteLine("    {0,12:x} : {1,6} {2,10:f1}", keyValue.Key, keyValue.Value.Item1, keyValue.Value.Item2);
            }

            if (sourceLocation == null)
            {
                return(null);
            }

            foreach (var keyVal in metricOnLine)
            {
                Console.WriteLine("    Line {0,5}:  Metric {1,5:n1}", keyVal.Key, keyVal.Value);
            }

            return(sourceLocation);
        }