/// <summary> /// Collects a gcdump from a currently running process. /// </summary> /// <param name="ct">The cancellation token</param> /// <param name="console"></param> /// <param name="processId">The process to collect the gcdump from.</param> /// <param name="output">The output path for the collected gcdump.</param> /// <returns></returns> private static async Task <int> Collect(CancellationToken ct, IConsole console, int processId, string output, int timeout, bool verbose) { try { output = string.IsNullOrEmpty(output) ? $"{DateTime.Now.ToString(@"yyyyMMdd\_hhmmss")}_{processId}.gcdump" : output; FileInfo outputFileInfo = new FileInfo(output); if (outputFileInfo.Exists) { outputFileInfo.Delete(); } if (string.IsNullOrEmpty(outputFileInfo.Extension) || outputFileInfo.Extension != ".gcdump") { outputFileInfo = new FileInfo(outputFileInfo.FullName + ".gcdump"); } Console.Out.WriteLine($"Writing gcdump to '{outputFileInfo.FullName}'..."); var dumpTask = Task.Run(() => { var memoryGraph = new Graphs.MemoryGraph(50_000); var heapInfo = new DotNetHeapInfo(); if (!EventPipeDotNetHeapDumper.DumpFromEventPipe(ct, processId, memoryGraph, verbose ? Console.Out : TextWriter.Null, timeout, heapInfo)) { return(false); } memoryGraph.AllowReading(); GCHeapDump.WriteMemoryGraph(memoryGraph, outputFileInfo.FullName, "dotnet-gcdump"); return(true); }); var fDumpSuccess = await dumpTask; if (fDumpSuccess) { outputFileInfo.Refresh(); Console.Out.WriteLine($"\tFinished writing {outputFileInfo.Length} bytes."); return(0); } else if (ct.IsCancellationRequested) { Console.Out.WriteLine($"\tCancelled."); return(-1); } else { Console.Out.WriteLine($"\tFailed to collect gcdump. Try running with '-v' for more information."); return(-1); } } catch (Exception ex) { Console.Error.WriteLine($"[ERROR] {ex.ToString()}"); return(-1); } }
internal static bool TryCollectMemoryGraph(CancellationToken ct, int processId, int timeout, bool verbose, out MemoryGraph memoryGraph) { var heapInfo = new DotNetHeapInfo(); var log = verbose ? Console.Out : TextWriter.Null; memoryGraph = new MemoryGraph(50_000); if (!EventPipeDotNetHeapDumper.DumpFromEventPipe(ct, processId, memoryGraph, log, timeout, heapInfo)) { return(false); } memoryGraph.AllowReading(); return(true); }
/// <summary> /// Collects a gcdump from a currently running process. /// </summary> /// <param name="ct">The cancellation token</param> /// <param name="console"></param> /// <param name="processId">The process to collect the gcdump from.</param> /// <param name="output">The output path for the collected gcdump.</param> /// <returns></returns> public static async Task <int> Collect(CancellationToken ct, CommandLineApplication cmd, int processId, string output, int timeout, bool verbose) { try { if (processId < 0) { return(cmd.ExitWithError($"The PID cannot be negative: {processId}")); } if (processId == 0) { return(cmd.ExitWithError($"-p|--process-id is required")); } output = string.IsNullOrEmpty(output) ? $"{DateTime.Now.ToString(@"yyyyMMdd\_hhmmss")}_{processId}.gcdump" : output; FileInfo outputFileInfo = new FileInfo(output); if (outputFileInfo.Exists) { outputFileInfo.Delete(); } if (string.IsNullOrEmpty(outputFileInfo.Extension) || outputFileInfo.Extension != ".gcdump") { outputFileInfo = new FileInfo(outputFileInfo.FullName + ".gcdump"); } cmd.Out.WriteLine($"Writing gcdump to '{outputFileInfo.FullName}'..."); var dumpTask = Task.Run(() => { var memoryGraph = new Graphs.MemoryGraph(50_000); var heapInfo = new DotNetHeapInfo(); if (!EventPipeDotNetHeapDumper.DumpFromEventPipe(ct, processId, memoryGraph, verbose ? cmd.Out : TextWriter.Null, timeout, heapInfo)) { return(false); } memoryGraph.AllowReading(); GCHeapDump.WriteMemoryGraph(memoryGraph, outputFileInfo.FullName, "dotnet-gcdump"); return(true); }); var fDumpSuccess = await dumpTask; if (fDumpSuccess) { outputFileInfo.Refresh(); cmd.Out.WriteLine($"\tFinished writing {new Size(outputFileInfo.Length, SizeUnit.Bytes)}."); return(0); } else if (ct.IsCancellationRequested) { cmd.Out.WriteLine($"\tCancelled."); return(-1); } else { cmd.Out.WriteLine($"\tFailed to collect gcdump. Try running with '-v' for more information."); return(-1); } } catch (Exception ex) { return(cmd.ExitWithError($"[ERROR] {ex}")); } }