Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

183 lines
5.0 KiB

  1. #ifndef __FUSION_PERFCLOCKING
  2. #define __FUSION_PERFCLOCKING
  3. typedef struct _tagFUSION_PERF_INFO
  4. {
  5. LARGE_INTEGER AccumulatedCycles;
  6. LARGE_INTEGER LineHits;
  7. BOOL bInitialized;
  8. int iSourceLine;
  9. CHAR *pSourceFile;
  10. CHAR *pStatement;
  11. #ifdef __cplusplus
  12. _tagFUSION_PERF_INFO() { AccumulatedCycles.QuadPart = LineHits.QuadPart = 0; bInitialized = FALSE; }
  13. #endif
  14. } FUSION_PERF_INFO, *PFUSION_PERF_INFO;
  15. #if defined(DBG) && defined(FUSION_PROFILING)
  16. #define PERFINFOTIME( pPerfInfo, statement ) \
  17. { \
  18. if ( !(pPerfInfo)->bInitialized ) { \
  19. (pPerfInfo)->iSourceLine = __LINE__; \
  20. (pPerfInfo)->pSourceFile = __FILE__; \
  21. (pPerfInfo)->pStatement = (#statement); \
  22. (pPerfInfo)->bInitialized = TRUE; \
  23. } \
  24. TIMEANDACCUMULATE( (pPerfInfo)->AccumulatedCycles, statement ); \
  25. (pPerfInfo)->LineHits.QuadPart++; \
  26. }
  27. #define CLOCKINTO( destiny ) \
  28. __asm { __asm cpuid __asm rdtsc }; \
  29. __asm { mov destiny.HighPart, edx }; \
  30. __asm { mov destiny.LowPart, eax };
  31. #define STARTCLOCK( destination, lag ) \
  32. { \
  33. LARGE_INTEGER __start, __stop; \
  34. LARGE_INTEGER *__pdest = &(destination), *__plag = &(lag); \
  35. CLOCKINTO( __start );
  36. #define STOPCLOCK() \
  37. CLOCKINTO( __stop ); \
  38. __pdest->QuadPart = __stop.QuadPart - ( __start.QuadPart + __plag->QuadPart ); \
  39. }
  40. #define STARTCLOCKACCUMULATE( accum, lag ) \
  41. { \
  42. LARGE_INTEGER __start, __stop; \
  43. LARGE_INTEGER *__acc = &(accum), *__plag = &(lag); \
  44. CLOCKINTO( __start ); \
  45. #define STOPCLOCKACCUMULATE() \
  46. CLOCKINTO( __stop ); \
  47. __acc->QuadPart += ( __stop.QuadPart - ( __start.QuadPart + __plag->QuadPart ) ); \
  48. }
  49. #define TIMEANDACCUMULATE( accumulator, statement ) \
  50. TIMEANDACCUMULATEWITHLAG( accumulator, statement, CpuIdLag )
  51. #define TIMEANDACCUMULATEWITHLAG( accumulator, statement, lag ) \
  52. STARTCLOCKACCUMULATE( accumulator, lag ); \
  53. statement; \
  54. STOPCLOCKACCUMULATE();
  55. #define FUSIONPERF_DUMP_TARGET_MASK ( 0x0000000F )
  56. #define FUSIONPERF_DUMP_TO_DEBUGGER ( 0x00000001 )
  57. #define FUSIONPERF_DUMP_TO_STDOUT ( 0x00000002 )
  58. #define FUSIONPERF_DUMP_TO_STDERR ( 0x00000003 )
  59. #define FUSIONPERF_DUMP_ALL_MASK ( 0x00000F00 )
  60. #define FUSIONPERF_DUMP_ALL_STATISTICS ( 0x00000100 )
  61. #define FUSIONPERF_DUMP_ALL_SOURCEINFO ( 0x00000200 )
  62. #define FUSIONPERF_DUMP_ALL_CONCISE ( 0x00000400 )
  63. #define FUSIONPERF_DUMP_TALLYS ( 0x00001000 )
  64. inline static VOID
  65. FusionpDumpPerfInfo( DWORD dwFlags, PFUSION_PERF_INFO pInfo )
  66. {
  67. CStringBuffer sbTemp;
  68. if ( dwFlags & FUSIONPERF_DUMP_ALL_SOURCEINFO )
  69. {
  70. sbTemp.Win32Format(
  71. L"Perf: %S(%d) - Hit %I64d times\n\t%I64d cycles total, %I64d average\n\t%S\n",
  72. pInfo->pSourceFile,
  73. pInfo->iSourceLine,
  74. pInfo->LineHits.QuadPart,
  75. pInfo->AccumulatedCycles.QuadPart,
  76. pInfo->AccumulatedCycles.QuadPart / pInfo->LineHits.QuadPart,
  77. pInfo->pStatement
  78. );
  79. }
  80. else if ( dwFlags & FUSIONPERF_DUMP_ALL_CONCISE )
  81. {
  82. sbTemp.Win32Format(
  83. L"%S(%d) - Hit %I64d times %I64d cycles total %I64d average\n",
  84. pInfo->pSourceFile,
  85. pInfo->iSourceLine,
  86. pInfo->LineHits.QuadPart,
  87. pInfo->AccumulatedCycles.QuadPart,
  88. pInfo->AccumulatedCycles.QuadPart / pInfo->LineHits.QuadPart
  89. );
  90. }
  91. else
  92. {
  93. sbTemp.Win32Format(
  94. L"Perf: %S(%d) - Hit %I64d times, \n\t%I64d cycles total, %I64d average\n",
  95. pInfo->pSourceFile,
  96. pInfo->iSourceLine,
  97. pInfo->LineHits.QuadPart,
  98. pInfo->AccumulatedCycles.QuadPart,
  99. pInfo->AccumulatedCycles.QuadPart / pInfo->LineHits.QuadPart
  100. );
  101. }
  102. switch ( dwFlags & FUSIONPERF_DUMP_TARGET_MASK )
  103. {
  104. case FUSIONPERF_DUMP_TO_DEBUGGER:
  105. OutputDebugString( sbTemp );
  106. break;
  107. case FUSIONPERF_DUMP_TO_STDOUT:
  108. wprintf( sbTemp );
  109. break;
  110. case FUSIONPERF_DUMP_TO_STDERR:
  111. fwprintf( stderr, sbTemp );
  112. break;
  113. }
  114. }
  115. inline static VOID
  116. FusionpReportPerfInfo( DWORD dwFlags, FUSION_PERF_INFO Info[], SIZE_T cInfo )
  117. {
  118. LARGE_INTEGER liAveragedTotalHits, liRawTotalCycles;
  119. liAveragedTotalHits.QuadPart = 0;
  120. liRawTotalCycles.QuadPart = 0;
  121. for ( SIZE_T i = 0; i < cInfo; i++ )
  122. {
  123. if ( dwFlags & FUSIONPERF_DUMP_ALL_STATISTICS )
  124. {
  125. FusionpDumpPerfInfo( dwFlags, Info + i );
  126. }
  127. liAveragedTotalHits.QuadPart +=
  128. ( Info[i].AccumulatedCycles.QuadPart / Info[i].LineHits.QuadPart );
  129. liRawTotalCycles.QuadPart += Info[i].AccumulatedCycles.QuadPart;
  130. }
  131. wprintf( L"Perf: Profiled %d statements, cyclecount average per set %I64d\n"
  132. L" %I64d total cycles in this set",
  133. cInfo,
  134. liAveragedTotalHits.QuadPart,
  135. liRawTotalCycles.QuadPart
  136. );
  137. }
  138. #define PERFINFOSINGLESTATEMENT( statement ) \
  139. { \
  140. FUSION_PERF_INFO __dumpinfo; \
  141. TIMEANDACCUMULATE( &__dumpinfo, statement ); \
  142. FusionpDumpPerfInfo( FUSIONPERF_DUMP_TO_STDOUT, &__dumpinfo ); \
  143. }
  144. #else
  145. #define PERFINFOTIME( pDump, statement ) statement;
  146. #define TIMEANDACCUMULATE( a, s ) s;
  147. #define TIMEANDACCUMULATEWITHLAG( a, s, l ) s;
  148. #define FusionpReportPerfInfo( a, b, c )
  149. #define FusionpDumpPerfInfo( a, b )
  150. #define PERFINFOSINGLESTATEMENT( statement ) statement;
  151. #endif
  152. #endif