Add ParallelStacks command to dotnet-dump (#1537)
authorchrisnas <chrisnas@users.noreply.github.com>
Thu, 10 Sep 2020 16:09:05 +0000 (18:09 +0200)
committerGitHub <noreply@github.com>
Thu, 10 Sep 2020 16:09:05 +0000 (09:09 -0700)
Add ParallelStacks command to dotnet-dump

Refactor ParallelStacks version

Keep consistent in naming ParalleStacks.Runtime version

eng/Versions.props
src/Tools/dotnet-dump/ExtensionCommands/MonoColorConsoleRenderer.cs [new file with mode: 0644]
src/Tools/dotnet-dump/ExtensionCommands/ParallelStacksCommand.cs [new file with mode: 0644]
src/Tools/dotnet-dump/dotnet-dump.csproj

index 794c21fd5fe9856f1456c14da45e6efe6182afd5..b17f918e044149e9772eddf502b37c7069c3338a 100644 (file)
@@ -40,6 +40,7 @@
     <MicrosoftBclAsyncInterfacesVersion>1.1.0</MicrosoftBclAsyncInterfacesVersion>
     <MicrosoftDiagnosticsRuntimeVersion>2.0.145801</MicrosoftDiagnosticsRuntimeVersion>
     <MicrosoftDiagnosticsRuntimeUtilitiesVersion>2.0.145801</MicrosoftDiagnosticsRuntimeUtilitiesVersion>
+    <ParallelStacksRuntimeVersion>2.0.1</ParallelStacksRuntimeVersion>
     <MicrosoftDiaSymReaderNativePackageVersion>1.7.0</MicrosoftDiaSymReaderNativePackageVersion>
     <MicrosoftDiagnosticsTracingTraceEventVersion>2.0.57</MicrosoftDiagnosticsTracingTraceEventVersion>
     <MicrosoftExtensionsConfigurationJsonVersion>2.1.1</MicrosoftExtensionsConfigurationJsonVersion>
diff --git a/src/Tools/dotnet-dump/ExtensionCommands/MonoColorConsoleRenderer.cs b/src/Tools/dotnet-dump/ExtensionCommands/MonoColorConsoleRenderer.cs
new file mode 100644 (file)
index 0000000..1735200
--- /dev/null
@@ -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 (file)
index 0000000..2626c34
--- /dev/null
@@ -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 +
+    ""
+    ;
+    }
+}
index d7450aa41929a94c90d6a5db30c5a86229de2121..f01f73eaca0a67ebb1889728990c0b7f09919077 100644 (file)
@@ -20,6 +20,7 @@
   <ItemGroup>
     <PackageReference Include="Microsoft.Diagnostics.Runtime" Version="$(MicrosoftDiagnosticsRuntimeVersion)" />
     <PackageReference Include="Microsoft.SymbolStore" Version="$(MicrosoftSymbolStoreVersion)" />
+    <PackageReference Include="ParallelStacks.Runtime" Version="$(ParallelStacksRuntimeVersion)" />
   </ItemGroup>
 
   <ItemGroup>