public AllocationTickMemoryProfiler(TraceEventSession session, int pid, ProcessAllocationInfo allocations, bool verbose = false) { if (session == null) { throw new NullReferenceException(nameof(session)); } _session = session; if (allocations == null) { throw new NullReferenceException(nameof(allocations)); } _allocations = allocations; _pid = pid; _verbose = verbose; _symbolLookupMessages = new StringWriter(); // By default a symbol Reader uses whatever is in the _NT_SYMBOL_PATH variable. However you can override // if you wish by passing it to the SymbolReader constructor. Since we want this to work even if you // have not set an _NT_SYMBOL_PATH, so we add the Microsoft default symbol server path to be sure/ var symbolPath = new SymbolPath(SymbolPath.SymbolPathFromEnvironment).Add(SymbolPath.MicrosoftSymbolServerPath); _symbolReader = new SymbolReader(_symbolLookupMessages, symbolPath.ToString()); // By default the symbol reader will NOT read PDBs from 'unsafe' locations (like next to the EXE) // because hackers might make malicious PDBs. If you wish ignore this threat, you can override this // check to always return 'true' for checking that a PDB is 'safe'. _symbolReader.SecurityCheck = (path => true); }
static async Task <int> Main(string[] args) { ShowHeader(); (int pid, bool verbose)parameters; try { parameters = GetParameters(args); } catch (InvalidOperationException x) { Console.WriteLine(x.Message); ShowHelp(); return(-1); } if (parameters.verbose) { Console.WriteLine($"Current pid = {Process.GetCurrentProcess().Id}"); Console.WriteLine($"Profiling process #{parameters.pid}..."); Console.WriteLine(); } var allocations = new ProcessAllocationInfo(parameters.pid); TraceEventSession session = new TraceEventSession( "AllocationTickMemoryProfilingSession", TraceEventSessionOptions.Create ); var profiler = new AllocationTickMemoryProfiler(session, parameters.pid, allocations, parameters.verbose); var task = profiler.StartAsync(); Console.WriteLine("Press ENTER to stop memory profiling"); Console.WriteLine(); Console.ReadLine(); // this will exit the session.Process() call session.Dispose(); try { await task; ShowResults(allocations); Console.WriteLine("Press ENTER to exit..."); Console.WriteLine(); Console.ReadLine(); return(0); } catch (Exception x) { Console.WriteLine(x.Message); ShowHelp(); } return(-666); }
private static void ShowResults(ProcessAllocationInfo allocations) { Console.WriteLine(" Small Large LOH Type"); Console.WriteLine("---------------------------------------------------------"); foreach (var allocation in allocations.GetAllocations().OrderByDescending(a => a.Count)) { var smallCount = (allocation.SmallCount == 0) ? " " : $"{allocation.SmallCount,7}"; var largeCount = (allocation.LargeCount == 0) ? " " : $"{allocation.LargeCount,7}"; var largeSize = (allocation.LargeSize == 0) ? " " : $"{allocation.LargeSize,10}"; Console.WriteLine($"{smallCount} {largeCount} {largeSize} {allocation.TypeName}"); } }
public AllocationTickMemoryProfiler(TraceEventSession session, int pid, ProcessAllocationInfo allocations, bool verbose = false) { if (session == null) { throw new NullReferenceException(nameof(session)); } _session = session; if (allocations == null) { throw new NullReferenceException(nameof(allocations)); } _allocations = allocations; _pid = pid; _verbose = verbose; }