|
|
#ifndef __FUSION_PERFCLOCKING
#define __FUSION_PERFCLOCKING
typedef struct _tagFUSION_PERF_INFO { LARGE_INTEGER AccumulatedCycles; LARGE_INTEGER LineHits; BOOL bInitialized; int iSourceLine; CHAR *pSourceFile; CHAR *pStatement;
#ifdef __cplusplus
_tagFUSION_PERF_INFO() { AccumulatedCycles.QuadPart = LineHits.QuadPart = 0; bInitialized = FALSE; } #endif
} FUSION_PERF_INFO, *PFUSION_PERF_INFO;
#if defined(DBG) && defined(FUSION_PROFILING)
#define PERFINFOTIME( pPerfInfo, statement ) \
{ \ if ( !(pPerfInfo)->bInitialized ) { \ (pPerfInfo)->iSourceLine = __LINE__; \ (pPerfInfo)->pSourceFile = __FILE__; \ (pPerfInfo)->pStatement = (#statement); \ (pPerfInfo)->bInitialized = TRUE; \ } \ TIMEANDACCUMULATE( (pPerfInfo)->AccumulatedCycles, statement ); \ (pPerfInfo)->LineHits.QuadPart++; \ }
#define CLOCKINTO( destiny ) \
__asm { __asm cpuid __asm rdtsc }; \ __asm { mov destiny.HighPart, edx }; \ __asm { mov destiny.LowPart, eax };
#define STARTCLOCK( destination, lag ) \
{ \ LARGE_INTEGER __start, __stop; \ LARGE_INTEGER *__pdest = &(destination), *__plag = &(lag); \ CLOCKINTO( __start );
#define STOPCLOCK() \
CLOCKINTO( __stop ); \ __pdest->QuadPart = __stop.QuadPart - ( __start.QuadPart + __plag->QuadPart ); \ }
#define STARTCLOCKACCUMULATE( accum, lag ) \
{ \ LARGE_INTEGER __start, __stop; \ LARGE_INTEGER *__acc = &(accum), *__plag = &(lag); \ CLOCKINTO( __start ); \
#define STOPCLOCKACCUMULATE() \
CLOCKINTO( __stop ); \ __acc->QuadPart += ( __stop.QuadPart - ( __start.QuadPart + __plag->QuadPart ) ); \ }
#define TIMEANDACCUMULATE( accumulator, statement ) \
TIMEANDACCUMULATEWITHLAG( accumulator, statement, CpuIdLag )
#define TIMEANDACCUMULATEWITHLAG( accumulator, statement, lag ) \
STARTCLOCKACCUMULATE( accumulator, lag ); \ statement; \ STOPCLOCKACCUMULATE();
#define FUSIONPERF_DUMP_TARGET_MASK ( 0x0000000F )
#define FUSIONPERF_DUMP_TO_DEBUGGER ( 0x00000001 )
#define FUSIONPERF_DUMP_TO_STDOUT ( 0x00000002 )
#define FUSIONPERF_DUMP_TO_STDERR ( 0x00000003 )
#define FUSIONPERF_DUMP_ALL_MASK ( 0x00000F00 )
#define FUSIONPERF_DUMP_ALL_STATISTICS ( 0x00000100 )
#define FUSIONPERF_DUMP_ALL_SOURCEINFO ( 0x00000200 )
#define FUSIONPERF_DUMP_ALL_CONCISE ( 0x00000400 )
#define FUSIONPERF_DUMP_TALLYS ( 0x00001000 )
inline static VOID FusionpDumpPerfInfo( DWORD dwFlags, PFUSION_PERF_INFO pInfo ) { CStringBuffer sbTemp;
if ( dwFlags & FUSIONPERF_DUMP_ALL_SOURCEINFO ) { sbTemp.Win32Format( L"Perf: %S(%d) - Hit %I64d times\n\t%I64d cycles total, %I64d average\n\t%S\n", pInfo->pSourceFile, pInfo->iSourceLine, pInfo->LineHits.QuadPart, pInfo->AccumulatedCycles.QuadPart, pInfo->AccumulatedCycles.QuadPart / pInfo->LineHits.QuadPart, pInfo->pStatement ); } else if ( dwFlags & FUSIONPERF_DUMP_ALL_CONCISE ) { sbTemp.Win32Format( L"%S(%d) - Hit %I64d times %I64d cycles total %I64d average\n", pInfo->pSourceFile, pInfo->iSourceLine, pInfo->LineHits.QuadPart, pInfo->AccumulatedCycles.QuadPart, pInfo->AccumulatedCycles.QuadPart / pInfo->LineHits.QuadPart ); } else { sbTemp.Win32Format( L"Perf: %S(%d) - Hit %I64d times, \n\t%I64d cycles total, %I64d average\n", pInfo->pSourceFile, pInfo->iSourceLine, pInfo->LineHits.QuadPart, pInfo->AccumulatedCycles.QuadPart, pInfo->AccumulatedCycles.QuadPart / pInfo->LineHits.QuadPart ); }
switch ( dwFlags & FUSIONPERF_DUMP_TARGET_MASK ) { case FUSIONPERF_DUMP_TO_DEBUGGER: OutputDebugString( sbTemp ); break; case FUSIONPERF_DUMP_TO_STDOUT: wprintf( sbTemp ); break; case FUSIONPERF_DUMP_TO_STDERR: fwprintf( stderr, sbTemp ); break; } }
inline static VOID FusionpReportPerfInfo( DWORD dwFlags, FUSION_PERF_INFO Info[], SIZE_T cInfo ) { LARGE_INTEGER liAveragedTotalHits, liRawTotalCycles; liAveragedTotalHits.QuadPart = 0; liRawTotalCycles.QuadPart = 0;
for ( SIZE_T i = 0; i < cInfo; i++ ) { if ( dwFlags & FUSIONPERF_DUMP_ALL_STATISTICS ) { FusionpDumpPerfInfo( dwFlags, Info + i ); }
liAveragedTotalHits.QuadPart += ( Info[i].AccumulatedCycles.QuadPart / Info[i].LineHits.QuadPart ); liRawTotalCycles.QuadPart += Info[i].AccumulatedCycles.QuadPart; }
wprintf( L"Perf: Profiled %d statements, cyclecount average per set %I64d\n" L" %I64d total cycles in this set", cInfo, liAveragedTotalHits.QuadPart, liRawTotalCycles.QuadPart ); }
#define PERFINFOSINGLESTATEMENT( statement ) \
{ \ FUSION_PERF_INFO __dumpinfo; \ TIMEANDACCUMULATE( &__dumpinfo, statement ); \ FusionpDumpPerfInfo( FUSIONPERF_DUMP_TO_STDOUT, &__dumpinfo ); \ }
#else
#define PERFINFOTIME( pDump, statement ) statement;
#define TIMEANDACCUMULATE( a, s ) s;
#define TIMEANDACCUMULATEWITHLAG( a, s, l ) s;
#define FusionpReportPerfInfo( a, b, c )
#define FusionpDumpPerfInfo( a, b )
#define PERFINFOSINGLESTATEMENT( statement ) statement;
#endif
#endif
|