x) Added enum for CommitResults x) Created interface IID<TS> x) Implemented DB class with lock, objects, committed lists x) Updated lookup and checkout methods in DB class x) Added TxStates enum and implemented Tx class with checkout, add, dispose methods x) Implemented commit method in DB class to handle transactions efficiently
163 lines
4.3 KiB
C#
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 async Task<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( $"" );
|
|
}
|
|
}
|
|
}
|