From 9d32dc2e37ac82ebc6549530d50a2e439fae15fa Mon Sep 17 00:00:00 2001 From: chrisnas Date: Thu, 10 Sep 2020 18:09:05 +0200 Subject: [PATCH] Add ParallelStacks command to dotnet-dump (#1537) Add ParallelStacks command to dotnet-dump Refactor ParallelStacks version Keep consistent in naming ParalleStacks.Runtime version --- eng/Versions.props | 1 + .../MonoColorConsoleRenderer.cs | 76 ++++++++++++++++ .../ParallelStacksCommand.cs | 91 +++++++++++++++++++ src/Tools/dotnet-dump/dotnet-dump.csproj | 1 + 4 files changed, 169 insertions(+) create mode 100644 src/Tools/dotnet-dump/ExtensionCommands/MonoColorConsoleRenderer.cs create mode 100644 src/Tools/dotnet-dump/ExtensionCommands/ParallelStacksCommand.cs diff --git a/eng/Versions.props b/eng/Versions.props index 794c21fd5..b17f918e0 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -40,6 +40,7 @@ 1.1.0 2.0.145801 2.0.145801 + 2.0.1 1.7.0 2.0.57 2.1.1 diff --git a/src/Tools/dotnet-dump/ExtensionCommands/MonoColorConsoleRenderer.cs b/src/Tools/dotnet-dump/ExtensionCommands/MonoColorConsoleRenderer.cs new file mode 100644 index 000000000..1735200db --- /dev/null +++ b/src/Tools/dotnet-dump/ExtensionCommands/MonoColorConsoleRenderer.cs @@ -0,0 +1,76 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using Microsoft.Diagnostics.DebugServices; +using ParallelStacks.Runtime; + +namespace Microsoft.Diagnostic.Tools.Dump.ExtensionCommands +{ + public class MonoColorConsoleRenderer : RendererBase + { + private readonly IConsoleService _console; + + public MonoColorConsoleRenderer(IConsoleService console, int limit = -1) : base(limit) + { + _console = console; + } + + public override void Write(string text) + { + Output(text); + } + + public override void WriteCount(string count) + { + Output(count); + } + + public override void WriteNamespace(string ns) + { + Output(ns); + } + + public override void WriteType(string type) + { + Output(type); + } + + public override void WriteSeparator(string separator) + { + Output(separator); + } + + public override void WriteDark(string separator) + { + Output(separator); + } + + public override void WriteMethod(string method) + { + Output(method); + } + + public override void WriteMethodType(string type) + { + Output(type); + } + + public override void WriteFrameSeparator(string text) + { + Output(text); + } + + public override string FormatTheadId(uint threadID) + { + var idInHex = threadID.ToString("x"); + return idInHex; + } + + private void Output(string text) + { + _console.Write(text); + } + } +} diff --git a/src/Tools/dotnet-dump/ExtensionCommands/ParallelStacksCommand.cs b/src/Tools/dotnet-dump/ExtensionCommands/ParallelStacksCommand.cs new file mode 100644 index 000000000..2626c34b9 --- /dev/null +++ b/src/Tools/dotnet-dump/ExtensionCommands/ParallelStacksCommand.cs @@ -0,0 +1,91 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using Microsoft.Diagnostics.Repl; +using Microsoft.Diagnostics.Runtime; +using ParallelStacks.Runtime; + +namespace Microsoft.Diagnostic.Tools.Dump.ExtensionCommands +{ + [Command(Name = "parallelstacks", Help = "Display merged threads stack a la Visual Studio 'Parallel Stacks' panel.")] + [CommandAlias(Name = "pstacks")] + public class ParallelStacksCommand : ExtensionCommandBase + { + public ClrRuntime Runtime { get; set; } + + [Option(Name = "--allThreads", Help = "Displays all threads per group instead of at most 4 by default.")] + [OptionAlias(Name = "-a")] + public bool AllThreads { get; set; } + + + public override void Invoke() + { + var ps = ParallelStacks.Runtime.ParallelStack.Build(Runtime); + if (ps == null) + { + return; + } + + int threadIDsCountLimit = AllThreads ? -1 : 4; // by default, show at most 4 thread ID per group + + var visitor = new MonoColorConsoleRenderer(Console, limit: threadIDsCountLimit); + WriteLine(""); + foreach (var stack in ps.Stacks) + { + Write("________________________________________________"); + stack.Render(visitor); + WriteLine(""); + WriteLine(""); + WriteLine(""); + } + + WriteLine($"==> {ps.ThreadIds.Count} threads with {ps.Stacks.Count} roots{Environment.NewLine}"); + + } + + protected override string GetDetailedHelp() + { + return DetailedHelpText; + } + + readonly string DetailedHelpText = + "-------------------------------------------------------------------------------" + Environment.NewLine + + "ParallelStacks" + Environment.NewLine + + Environment.NewLine + + "pstacks groups the callstack of all running threads and shows a merged display a la Visual Studio 'Parallel Stacks' panel" + Environment.NewLine + + "By default, only 4 threads ID per frame group are listed. Use --allThreads/-a to list all threads ID." + Environment.NewLine + + Environment.NewLine + + "> pstacks" + Environment.NewLine + + "________________________________________________" + Environment.NewLine + + "~~~~ 8f8c" + Environment.NewLine + + " 1 (dynamicClass).IL_STUB_PInvoke(IntPtr, Byte*, Int32, Int32 ByRef, IntPtr)" + Environment.NewLine + + " ..." + Environment.NewLine + + " 1 System.Console.ReadLine()" + Environment.NewLine + + " 1 NetCoreConsoleApp.Program.Main(String[])" + Environment.NewLine + + Environment.NewLine + + "________________________________________________" + Environment.NewLine + + " ~~~~ 7034" + Environment.NewLine + + " 1 System.Threading.Monitor.Wait(Object, Int32, Boolean)" + Environment.NewLine + + " ..." + Environment.NewLine + + " 1 System.Threading.Tasks.Task.Wait()" + Environment.NewLine + + " 1 NetCoreConsoleApp.Program+c.b__1_4(Object)" + Environment.NewLine + + " ~~~~ 9c6c,4020" + Environment.NewLine + + " 2 System.Threading.Monitor.Wait(Object, Int32, Boolean)" + Environment.NewLine + + " ..." + Environment.NewLine + + " 2 NetCoreConsoleApp.Program+c__DisplayClass1_0.b__7()" + Environment.NewLine + + " 3 System.Threading.Tasks.Task.InnerInvoke()" + Environment.NewLine + + " 4 System.Threading.Tasks.Task+c.cctor>b__278_1(Object)" + Environment.NewLine + + " ..." + Environment.NewLine + + " 4 System.Threading.Tasks.Task.ExecuteEntryUnsafe()" + Environment.NewLine + + " 4 System.Threading.Tasks.Task.ExecuteWorkItem()" + Environment.NewLine + + " 7 System.Threading.ThreadPoolWorkQueue.Dispatch()" + Environment.NewLine + + " 7 System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()" + Environment.NewLine + + Environment.NewLine + + "==> 8 threads with 2 roots" + Environment.NewLine + + Environment.NewLine + + "" + ; + } +} diff --git a/src/Tools/dotnet-dump/dotnet-dump.csproj b/src/Tools/dotnet-dump/dotnet-dump.csproj index d7450aa41..f01f73eac 100644 --- a/src/Tools/dotnet-dump/dotnet-dump.csproj +++ b/src/Tools/dotnet-dump/dotnet-dump.csproj @@ -20,6 +20,7 @@ + -- 2.34.1