sharplib/prof/Program.cs
Marc Hernandez f873c42cbf fix(logging): Account for nullable value types
This commit updates logging to handle nullable value types and parameters.

The following changes were made:
- Updated the Value record to use '!' instead of '?' for nullability.
- Added '!' to the default Value.
- Added '!= null' checks to conditional assignment.
- Removed unnecessary nullable-disable compiler directives.
2024-08-15 22:26:47 -07:00

163 lines
4.3 KiB
C#

using Microsoft.Diagnostics.Tracing.Session;
using ProfilerHelpers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace Tracing
{
static class Program
{
static public int CreateTracingSession( bool noSampling, bool sortBySize, int topTypesLimit )
{
ShowHeader();
try
{
TraceEventSession session = new TraceEventSession(
"Tracing",
TraceEventSessionOptions.Create
);
log.info( $"Create PerProcessProfilingState" );
using( var processes = new PerProcessProfilingState() )
{
log.info( $"Create Memory profiler for session" );
var profiler = new Memory( session, processes );
log.info( $"Start task" );
var task = profiler.StartAsync( noSampling );
/*
log.info( $"await the Continue" );
await task.ContinueWith( ( t ) => {
log.info( $"Task is done, Dispose" );
session.Dispose();
} );
*/
//log.info("Press ENTER to stop memory profiling");
//Console.ReadLine();
/*
try
{
await task;
ShowResults( processes, sortBySize, topTypesLimit );
return 0;
}
catch( Exception x )
{
log.info( x.Message );
ShowHelp();
}
*/
}
return -1;
}
catch( Exception x )
{
log.info( x.Message );
ShowHelp();
}
return -2;
}
private static void ShowResults( PerProcessProfilingState processes, bool sortBySize, int topTypesLimit )
{
foreach( var pid in processes.Allocations.Keys )
{
// skip processes without symbol resolution
if( !processes.Methods.ContainsKey( pid ) )
continue;
// skip processes without allocations
if( !processes.Allocations[pid].GetAllAllocations().Any() )
continue;
ShowResults( GetProcessName( pid, processes.Names ), processes.Methods[pid], processes.Allocations[pid], sortBySize, topTypesLimit );
}
}
private static string GetProcessName( int pid, Dictionary<int, string> names )
{
if( names.TryGetValue( pid, out var name ) )
return name;
return pid.ToString();
}
private static void ShowResults( string name, MethodStore methods, ProcessAllocations allocations, bool sortBySize, int topTypesLimit )
{
log.info( $"Memory allocations for {name}" );
log.info( $"" );
log.info( "---------------------------------------------------------" );
log.info( " Count Size Type" );
log.info( "---------------------------------------------------------" );
IEnumerable<AllocationInfo> types = ( sortBySize )
? allocations.GetAllAllocations().OrderByDescending( a => a.Size )
: allocations.GetAllAllocations().OrderByDescending( a => a.Count )
;
if( topTypesLimit != -1 )
types = types.Take( topTypesLimit );
foreach( var allocation in types )
{
log.info( $"{allocation.Count,9} {allocation.Size,11} {allocation.TypeName}" );
log.info( $"" );
DumpStacks( allocation, methods );
log.info( $"" );
}
log.info( $"" );
log.info( $"" );
}
private static void DumpStacks( AllocationInfo allocation, MethodStore methods )
{
var stacks = allocation.Stacks.OrderByDescending( s => s.Count ).Take( 10 );
foreach( var stack in stacks )
{
log.info( $"{stack.Count,6} allocations" );
log.info( "----------------------------------" );
DumpStack( stack.Stack, methods );
log.info( $"" );
}
}
private static void DumpStack( AddressStack stack, MethodStore methods )
{
var callstack = stack.Stack;
for( int i = 0; i < Math.Min( 10, callstack.Count ); i++ )
{
log.info( $" {methods.GetFullName( callstack[i] )}" );
}
}
private static void ShowHeader()
{
log.info( "Tracing v1.0.0 - Sampled memory profiler for .NET applications" );
log.info( "by Christophe Nasarre" );
log.info( $"" );
}
private static void ShowHelp()
{
log.info( $"" );
log.info( "Tracing shows sampled allocations of a given .NET application." );
log.info( "Usage: Tracing [-a (all allocations)] [-c (sort by count instead of default by size)] [-t <type count (instead of 3 types by default)>]" );
log.info( " Ex: Tracing -t -1 (all types sampled allocations sorted by size)" );
log.info( " Ex: Tracing -c -t 10 (allocations for top 10 types sorted by count)" );
log.info( $"" );
}
}
}