public static ParallelStack Build(string dumpFile, string dacFilePath) { DataTarget dataTarget = null; ParallelStack ps = null; try { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { dataTarget = DataTarget.LoadCrashDump(dumpFile); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { dataTarget = DataTarget.LoadCoreDump(dumpFile); } else { throw new InvalidOperationException("Unsupported platform..."); } var runtime = CreateRuntime(dataTarget, dacFilePath); if (runtime == null) { return(null); } ps = ParallelStack.Build(runtime); } finally { dataTarget?.Dispose(); } return(ps); }
private static void RenderStack(ParallelStack stack, IRenderer visitor, int increment = 0) { var alignment = new string(' ', Padding *increment); if (stack.Stacks.Count == 0) { var lastFrame = stack.Frame; visitor.Write($"{Environment.NewLine}{alignment}"); visitor.WriteFrameSeparator($" ~~~~ {FormatThreadIdList(visitor, stack.ThreadIds)}"); visitor.WriteCount($"{Environment.NewLine}{alignment}{stack.ThreadIds.Count,Padding} "); RenderFrame(lastFrame, visitor); return; } foreach (var nextStackFrame in stack.Stacks.OrderBy(s => s.ThreadIds.Count)) { RenderStack(nextStackFrame, visitor, (nextStackFrame.ThreadIds.Count == stack.ThreadIds.Count) ? increment : increment + 1); } var currentFrame = stack.Frame; visitor.WriteCount($"{Environment.NewLine}{alignment}{stack.ThreadIds.Count,Padding} "); RenderFrame(currentFrame, visitor); }
private static void RenderStackHtml(ParallelStack stack, IHtmlRenderer visitor, int increment = 0) { if (stack.Stacks.Count == 0) { var lastFrame = stack.Frame; visitor.EnterFrameGroupEnd(increment); visitor.WriteFrameSeparator($" ~~~~ {FormatThreadIdList(visitor, stack.ThreadIds)}"); visitor.LeaveFrameGroupEnd(); visitor.EnterFrame(increment); visitor.WriteCount($"{stack.ThreadIds.Count,Padding}"); RenderFrame(lastFrame, visitor); visitor.LeaveFrame(); return; } foreach (var nextStackFrame in stack.Stacks.OrderBy(s => s.ThreadIds.Count)) { RenderStackHtml(nextStackFrame, visitor, (nextStackFrame.ThreadIds.Count == stack.ThreadIds.Count) ? increment : increment + 1); } var currentFrame = stack.Frame; visitor.EnterFrame(increment); visitor.WriteCount($"{stack.ThreadIds.Count,Padding}"); RenderFrame(currentFrame, visitor); visitor.LeaveFrame(); }
public static ParallelStack Build(ClrRuntime runtime) { var ps = new ParallelStack(); var stackFrames = new List <ClrStackFrame>(64); foreach (var thread in runtime.Threads) { stackFrames.Clear(); foreach (var stackFrame in thread.StackTrace.Reverse()) { if (stackFrame.Kind != ClrStackFrameType.ManagedMethod) { continue; } stackFrames.Add(stackFrame); } if (stackFrames.Count == 0) { continue; } ps.AddStack(thread.OSThreadId, stackFrames.ToArray()); } return(ps); }
public static ParallelStack Build(ClrRuntime runtime) { var ps = new ParallelStack(); var stackFrames = new List <ClrStackFrame>(64); foreach (var thread in runtime.Threads) { stackFrames.Clear(); #if ClrMD1 foreach (var stackFrame in thread.StackTrace.Reverse()) #else foreach (var stackFrame in thread.EnumerateStackTrace().Reverse()) #endif { #if ClrMD1 if (stackFrame.Kind != ClrStackFrameType.ManagedMethod) #else if ((stackFrame.Kind != ClrStackFrameKind.ManagedMethod) || (stackFrame.Method == null)) #endif { continue; } stackFrames.Add(stackFrame); } if (stackFrames.Count == 0) { continue; } ps.AddStack(thread.OSThreadId, stackFrames.ToArray()); } return(ps); }
public static void RenderHtml(this ParallelStack stacks, IHtmlRenderer visitor) { visitor.EnterRender(stacks); foreach (var stack in stacks.Stacks) { visitor.EnterStackRoot(); RenderStackHtml(stack, visitor); visitor.LeaveStackRoot(); } visitor.EndRender(); }
public static ParallelStack Build(int pid, string dacFilePath) { DataTarget dataTarget = null; ParallelStack ps = null; try { #if ClrMD1 const uint msecTimeout = 2000; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { dataTarget = DataTarget.AttachToProcess(pid, msecTimeout, AttachFlag.NonInvasive); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { // ClrMD implementation for Linux is available only for Passive dataTarget = DataTarget.AttachToProcess(pid, msecTimeout, AttachFlag.Passive); } #else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { dataTarget = DataTarget.AttachToProcess(pid, true); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { // ClrMD implementation for Linux is available only for Passive dataTarget = DataTarget.AttachToProcess(pid, true); } #endif else { throw new InvalidOperationException("Unsupported platform..."); } var runtime = CreateRuntime(dataTarget, dacFilePath); if (runtime == null) { return(null); } ps = ParallelStack.Build(runtime); } finally { dataTarget?.Dispose(); } return(ps); }
private void AddStack(uint threadId, ClrStackFrame[] frames, int index = 0) { ThreadIds.Add(threadId); var firstFrame = frames[index].DisplayString; var callstack = Stacks.FirstOrDefault(s => s.Frame.Text == firstFrame); if (callstack == null) { callstack = new ParallelStack(frames[index]); Stacks.Add(callstack); } if (index == frames.Length - 1) { callstack.ThreadIds.Add(threadId); return; } callstack.AddStack(threadId, frames, index + 1); }
public static void Run(string name, string version, string[] args) { if (args.Length == 0) { ShowHelp(name, version, "Missing dump file path or process ID..."); return; } string dacFilePath = (args.Length >= 2) ? args[1] : null; if (dacFilePath != null) { if (!File.Exists(dacFilePath)) { Console.WriteLine($"{dacFilePath} file does not exist..."); return; } } ParallelStack ps; var input = args[0]; // attach to live process if (int.TryParse(input, out var pid)) { try { ps = ParallelStack.Build(pid, dacFilePath); } catch (InvalidOperationException x) { Console.WriteLine($"Impossible to build call stacks: {x.Message}"); return; } } // open memory dump else { if (!File.Exists(input)) { Console.WriteLine($"'{input}' does not exist..."); return; } try { ps = ParallelStack.Build(input, dacFilePath); } catch (InvalidOperationException x) { Console.WriteLine($"Impossible to build call stacks: {x.Message}"); return; } } int threadIDsCountlimit = 4; var visitor = new ConsoleRenderer(useDml: false, limit: threadIDsCountlimit); Console.WriteLine(); foreach (var stack in ps.Stacks) { Console.Write("________________________________________________"); stack.Render(visitor); Console.WriteLine(); Console.WriteLine(); Console.WriteLine(); } Console.WriteLine($"==> {ps.ThreadIds.Count} threads with {ps.Stacks.Count} roots{Environment.NewLine}"); }
public static void Render(this ParallelStack stacks, IRenderer visitor) { RenderStack(stacks, visitor); }
public override void EnterRender(ParallelStack stacks) { _bufferHtml.Append($"<p><span class=\"{TitleClassName}\">{stacks.ThreadIds.Count} threads for {stacks.Stacks.Count} roots</span></p>"); }