Пример #1
0
        public static void WriteStacks(StackSource source, XmlWriter writer)
        {
            writer.WriteStartElement("StackSource");
            writer.WriteStartElement("Frames");
            writer.WriteAttributeString("Count", source.CallFrameIndexLimit.ToString());
            for (int i = 0; i < source.CallFrameIndexLimit; i++)
            {
                writer.WriteStartElement("Frame");
                writer.WriteAttributeString("ID", i.ToString());
                var frameName = source.GetFrameName((StackSourceFrameIndex)i, true);

                writer.WriteString(frameName);
                writer.WriteEndElement(); // Frame
            }
            writer.WriteEndElement();     // Frames

            writer.WriteStartElement("Stacks");
            writer.WriteAttributeString("Count", source.CallStackIndexLimit.ToString());
            for (int i = 0; i < source.CallStackIndexLimit; i++)
            {
                writer.WriteStartElement("Stack");
                writer.WriteAttributeString("ID", i.ToString());
                var FrameID  = source.GetFrameIndex((StackSourceCallStackIndex)i);
                var callerID = source.GetCallerIndex((StackSourceCallStackIndex)i);
                writer.WriteAttributeString("CallerID", ((int)callerID).ToString());
                writer.WriteAttributeString("FrameID", ((int)FrameID).ToString());
                writer.WriteEndElement(); // Stack
            }
            writer.WriteEndElement();     // Stacks

            writer.WriteStartElement("Samples");
            writer.WriteAttributeString("Count", source.SampleIndexLimit.ToString());
            // We use the invariant culture, otherwise if we encode in France and decode
            // in English we get parse errors (this happened!);
            var invariantCulture = CultureInfo.InvariantCulture;

            source.ForEach(delegate(StackSourceSample sample)
            {
                // <Sample ID="1" Time="3432.23" StackID="2" Metric="1" EventKind="CPUSample" />
                writer.WriteStartElement("Sample");
                writer.WriteAttributeString("ID", ((int)sample.SampleIndex).ToString());
                writer.WriteAttributeString("Time", sample.TimeRelativeMSec.ToString("f3", invariantCulture));
                writer.WriteAttributeString("StackID", ((int)sample.StackIndex).ToString());
                if (sample.Metric != 1)
                {
                    var asInt = (int)sample.Metric;
                    if (sample.Metric == asInt)
                    {
                        writer.WriteAttributeString("Metric", asInt.ToString());
                    }
                    else
                    {
                        writer.WriteAttributeString("Metric", sample.Metric.ToString("f3", invariantCulture));
                    }
                }
                writer.WriteEndElement();
            });
            writer.WriteEndElement(); // Samples
            writer.WriteEndElement(); // StackSource
        }
Пример #2
0
        public static void WriteStacks(StackSource source, XmlWriter writer)
        {
            writer.WriteStartElement("StackSource");
            writer.WriteStartElement("Frames");
            writer.WriteAttributeString("Count", source.CallFrameIndexLimit.ToString());
            for (int i = 0; i < source.CallFrameIndexLimit; i++)
            {
                writer.WriteStartElement("Frame");
                writer.WriteAttributeString("ID", i.ToString());
                var frameName = source.GetFrameName((StackSourceFrameIndex)i, true);

                // Check for the optimization tier. The frame name would contain the optimization tier in the form:
                //   Module![OptimizationTier]Symbol
                // Extract the optimization tier into an attribute and convert the frame name to this form for storage:
                //   Module!Symbol
                if (frameName != null && frameName.Length >= 4)
                {
                    int openBracketIndex = frameName.IndexOf("![") + 1;
                    if (openBracketIndex > 0)
                    {
                        int closeBracketIndex = frameName.IndexOf(']', openBracketIndex + 1);
                        if (closeBracketIndex - openBracketIndex > 1)
                        {
                            var optimizationTierStr =
                                frameName.Substring(openBracketIndex + 1, closeBracketIndex - openBracketIndex - 1);
                            if (Enum.TryParse <OptimizationTier>(optimizationTierStr, out var optimizationTier))
                            {
                                if (optimizationTier != OptimizationTier.Unknown)
                                {
                                    writer.WriteAttributeString("OptimizationTier", optimizationTierStr);
                                }
                                frameName = frameName.Substring(0, openBracketIndex) + frameName.Substring(closeBracketIndex + 1);
                            }
                        }
                    }
                }

                writer.WriteString(frameName);
                writer.WriteEndElement(); // Frame
            }
            writer.WriteEndElement();     // Frames

            writer.WriteStartElement("Stacks");
            writer.WriteAttributeString("Count", source.CallStackIndexLimit.ToString());
            for (int i = 0; i < source.CallStackIndexLimit; i++)
            {
                writer.WriteStartElement("Stack");
                writer.WriteAttributeString("ID", i.ToString());
                var FrameID  = source.GetFrameIndex((StackSourceCallStackIndex)i);
                var callerID = source.GetCallerIndex((StackSourceCallStackIndex)i);
                writer.WriteAttributeString("CallerID", ((int)callerID).ToString());
                writer.WriteAttributeString("FrameID", ((int)FrameID).ToString());
                writer.WriteEndElement(); // Stack
            }
            writer.WriteEndElement();     // Stacks

            writer.WriteStartElement("Samples");
            writer.WriteAttributeString("Count", source.SampleIndexLimit.ToString());
            // We use the invariant culture, otherwise if we encode in France and decode
            // in English we get parse errors (this happened!);
            var invariantCulture = CultureInfo.InvariantCulture;

            source.ForEach(delegate(StackSourceSample sample)
            {
                // <Sample ID="1" Time="3432.23" StackID="2" Metric="1" EventKind="CPUSample" />
                writer.WriteStartElement("Sample");
                writer.WriteAttributeString("ID", ((int)sample.SampleIndex).ToString());
                writer.WriteAttributeString("Time", sample.TimeRelativeMSec.ToString("f3", invariantCulture));
                writer.WriteAttributeString("StackID", ((int)sample.StackIndex).ToString());
                if (sample.Metric != 1)
                {
                    var asInt = (int)sample.Metric;
                    if (sample.Metric == asInt)
                    {
                        writer.WriteAttributeString("Metric", asInt.ToString());
                    }
                    else
                    {
                        writer.WriteAttributeString("Metric", sample.Metric.ToString("f3", invariantCulture));
                    }
                }
                writer.WriteEndElement();
            });
            writer.WriteEndElement(); // Samples
            writer.WriteEndElement(); // StackSource
        }
        private static bool BuildInternalTempRepresentation(StackSource stackSource, string fileToWrite, string rootFunction)
        {
            StringBuilder flameChartStringBuilder = new StringBuilder();
            bool          enableRootingOnFunction = !string.IsNullOrWhiteSpace(rootFunction);

            // Write out the flame chart format, one line per stack
            // eg: corerun;foo;bar;baz 1
            stackSource.ForEach(sample =>
            {
                Stack <StackSourceCallStackIndex> callStackIndices = new Stack <StackSourceCallStackIndex>();

                callStackIndices.Push(sample.StackIndex);

                StackSourceCallStackIndex callerIdx = stackSource.GetCallerIndex(sample.StackIndex);
                while (callerIdx != StackSourceCallStackIndex.Invalid)
                {
                    callStackIndices.Push(callerIdx);
                    callerIdx = stackSource.GetCallerIndex(callerIdx);
                }

                bool firstOne          = true;
                bool foundRootFunction = false;
                while (callStackIndices.Count > 0)
                {
                    var currFrame = callStackIndices.Pop();
                    var frameIdx  = stackSource.GetFrameIndex(currFrame);

                    var frameName = stackSource.GetFrameName(frameIdx, false);

                    // If we're rooting on a function, skip the frames above it
                    if (enableRootingOnFunction && !foundRootFunction)
                    {
                        if (frameName.Contains(rootFunction))
                        {
                            foundRootFunction = true;
                        }
                        else
                        {
                            continue;
                        }
                    }

                    if (!firstOne)
                    {
                        flameChartStringBuilder.Append(";");
                    }

                    flameChartStringBuilder.Append(frameName);
                    firstOne = false;
                }

                flameChartStringBuilder.Append(" 1");
                flameChartStringBuilder.AppendLine();
            });

            using (TextWriter writer = File.CreateText(fileToWrite))
            {
                try
                {
                    writer.Write(flameChartStringBuilder.ToString());
                }
                catch (IOException)
                {
                    return(false);
                }
            }

            return(true);
        }
Пример #4
0
        /// <summary>
        /// Looks up symbols for all modules that have an inclusive count >= minCount.
        /// stackSource, if given, can be used to be the filter.  If null, 'this' is used.
        /// If stackSource is given, it needs to use the same indexes for frames as 'this'.
        /// shouldLoadSymbols, if given, can be used to filter the modules.
        /// </summary>
        public void LookupWarmSymbols(int minCount, SymbolReader reader, StackSource stackSource = null, Predicate <TraceModuleFile> shouldLoadSymbols = null)
        {
            if (stackSource == null)
            {
                stackSource = this;
            }

            Debug.Assert(stackSource.CallFrameIndexLimit == CallFrameIndexLimit);
            Debug.Assert(stackSource.CallStackIndexLimit == CallStackIndexLimit);

            reader.Log.WriteLine("Resolving all symbols for modules with inclusive times > {0}", minCount);
            if ((reader.Options & SymbolReaderOptions.CacheOnly) != 0)
            {
                reader.Log.WriteLine("Cache-Only set: will only look on the local machine.");
            }

            // Get a list of all the unique frames.   We also keep track of unique stacks for efficiency
            var stackModuleLists = new ModuleList[stackSource.CallStackIndexLimit];
            var stackCounts      = new int[stackSource.CallStackIndexLimit];
            var totalCount       = 0;

            // Compute for each stack, the set of inclusive modules for that stack
            stackSource.ForEach(delegate(StackSourceSample sample)
            {
                stackCounts[(int)sample.StackIndex]++;
                totalCount++;
            });
            reader.Log.WriteLine("Got a total of {0} samples", totalCount);

            // for each stack in the trace, find the list of modules for that stack
            var moduleCounts = new int[TraceLog.ModuleFiles.Count];

            for (int i = 0; i < stackCounts.Length; i++)
            {
                var count = stackCounts[i];
                if (count > 0)
                {
                    var modules = GetModulesForStack(stackModuleLists, (StackSourceCallStackIndex)i);
                    // Update the counts for each module in that stack.
                    while (modules != null)
                    {
                        moduleCounts[(int)modules.Module.ModuleFileIndex] += count;
                        modules = modules.Next;
                    }
                }
            }

            // Now that we have an list of the inclusive counts of all frames.  Find all stacks that meet the threshold
            for (int i = 0; i < moduleCounts.Length; i++)
            {
                if (moduleCounts[i] >= minCount)
                {
                    var moduleFile = TraceLog.ModuleFiles[(ModuleFileIndex)i];
                    if (shouldLoadSymbols == null || shouldLoadSymbols(moduleFile))
                    {
                        reader.Log.WriteLine("Resolving symbols (count={0}) for module {1} ", moduleCounts[i], moduleFile.FilePath);
                        TraceLog.CallStacks.CodeAddresses.LookupSymbolsForModule(reader, moduleFile);
                    }
                }
            }
            reader.Log.WriteLine("Done Resolving all symbols for modules with inclusive times > {0}", minCount);
        }
Пример #5
0
        public static Dictionary <string, CallTreeItem> GetCallTree(StackSource stacks, out float timePerStack)
        {
            var callTree     = new Dictionary <string, CallTreeItem>(StringComparer.OrdinalIgnoreCase);
            var currentStack = new HashSet <string>();

            void AddRecursively(StackSourceCallStackIndex index, int depth = 0, CallTreeItem parent = null)
            {
                var name = stacks.GetFrameName(stacks.GetFrameIndex(index), false);

                if (name == "BROKEN")
                {
                    return;
                }
                var isRecursion = !currentStack.Add(name);
                var caller      = stacks.GetCallerIndex(index);

                if (!callTree.TryGetValue(name, out var item))
                {
                    callTree.Add(name, item = new CallTreeItem(name));
                }
                if (!isRecursion)
                {
                    item.IncSamples++;
                }
                if (depth == 0)
                {
                    item.Samples++;
                }
                else
                {
                    item.AddCallee(parent);
                }
                parent?.AddCaller(item);

                if (caller != StackSourceCallStackIndex.Invalid)
                {
                    AddRecursively(caller, depth + 1, item);
                }
                if (!isRecursion)
                {
                    currentStack.Remove(name);
                }
            }

            var metric = float.NaN;

            stacks.ForEach(stack => {
                if (float.IsNaN(metric))
                {
                    metric = stack.Metric;
                }
                if (metric != stack.Metric)
                {
                    throw new Exception();
                }
                if (stack.Count != 1)
                {
                    throw new Exception();
                }
                AddRecursively(stack.StackIndex);
                AddRecursively(stack.StackIndex);
            });
            timePerStack = metric;
            return(callTree);
        }