public void WriteStackTree(StackTree tree) { _totalTreeWeight = tree.Root.Weight; WriteStackTreeNode(tree.Root, 0, 0); // TODO Find the real offsets based on the headers }
static void Main(string[] args) { string filename; string processName; if (args.Length < 2) { filename = @"C:\Temp\final.etl"; processName = "devenv"; } else { filename = args[0]; processName = args[1]; } var output = Console.Error; var symOutput = TextWriter.Null; var traceLog = TraceLog.OpenOrConvert(filename, new TraceLogOptions() { ConversionLog = output }); var simpleTraceLogProcess = traceLog.Processes.LastProcessWithName(processName); if (simpleTraceLogProcess == null) { Console.Error.WriteLine("Could not find process with name {0}", processName); Environment.Exit(1); } var symbolReader = new SymbolReader(symOutput, SymbolPath.SymbolPathFromEnvironment); symbolReader.SecurityCheck = (path => true); Stopwatch sw = Stopwatch.StartNew(); foreach (var module in simpleTraceLogProcess.LoadedModules) { if (ShouldLoadSymbolsForModule(module.FilePath)) { traceLog.CodeAddresses.LookupSymbolsForModule(symbolReader, module.ModuleFile); } } Console.Error.WriteLine($"Loaded symbols in {sw.ElapsedMilliseconds} ms"); bool buildFlameGraphNatively = true; // TODO Make configurable if (buildFlameGraphNatively) { sw.Restart(); var stackTree = new StackTree(simpleTraceLogProcess.EventsInProcess.ByEventType <SampledProfileTraceData>()); Console.Error.WriteLine($"Built stack tree in {sw.ElapsedMilliseconds} ms"); // stackTree.Dump(Console.Out); var writer = new SVGWriter(Console.Out, 1024, stackTree.MaxDepth); writer.WriteHeader(); writer.WriteEmbeddedJavaScript(); writer.WriteStackTree(stackTree); writer.WriteFooter(); } else { CreateFoldedStacksForFlameGraphScript(simpleTraceLogProcess.EventsInProcess.ByEventType <SampledProfileTraceData>()); } // TODO Make this a PerfView UserCommand -- but don't use the PerfView 'Stacks' API // because that would lock us in to only using this tool from within PerfView. Instead, // just use CommandEnvironment.OpenETLFile("file.etl").TraceLog to get a TraceLog instance // and work from there as above. }