Leaked source code of windows server 2003
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.

251 lines
6.7 KiB

  1. /* Copyright (c) 1999-2000 Microsoft Corporation */
  2. ///======================================================================
  3. //
  4. // Perf.c
  5. //
  6. // This file contains the performance counter initialization
  7. // and dump routines. The only part of this file you
  8. // must modify is the performance counter name table. Match
  9. // the names with the counters you define in perf.h
  10. //
  11. ///======================================================================
  12. #include "wdm.h"
  13. #include "perf.h"
  14. #include "debug.h"
  15. #if PERFORMANCE
  16. //**********************************************************************
  17. //
  18. // Modify this section for your counters
  19. //
  20. //
  21. // The names that correspond to the performance
  22. // counter indexes in perf.h
  23. //
  24. static char CounterNames[NUM_PERF_COUNTERS][32] = {
  25. //
  26. // Write path
  27. //
  28. "Write",
  29. "WriteComplete",
  30. "WriteTimeout",
  31. //
  32. // Read path
  33. //
  34. "StartUsbReadWorkItem",
  35. "UsbRead",
  36. "UsbReadCompletion",
  37. "CheckForQueuedUserReads",
  38. "GetUserData",
  39. "PutUserData",
  40. "CancelUsbReadIrp",
  41. "Read",
  42. "StartOrQueueIrp",
  43. "StartUserRead",
  44. "GetNextUserIrp",
  45. "CancelCurrentRead",
  46. "CancelQueuedIrp",
  47. "ReadTimeout",
  48. "IntervalReadTimeout",
  49. "CancelUsbReadWorkItem",
  50. //
  51. // USB Path
  52. //
  53. "UsbReadWritePacket",
  54. //
  55. // Serial path
  56. //
  57. "ProcessSerialWaits",
  58. //
  59. // Utils
  60. //
  61. "TryToCompleteCurrentIrp",
  62. "RundownIrpRefs",
  63. "RecycleIrp",
  64. "ReuseIrp",
  65. "CalculateTimeout",
  66. };
  67. //
  68. // End of user-modified portion
  69. //
  70. //**********************************************************************
  71. // print macro that only turns on when debugging is on
  72. //#if DBG
  73. #define PerfPrint(arg) DbgPrint arg
  74. //#else
  75. //#define PerfPrint(arg)
  76. //#endif
  77. //
  78. // The array of performance counters
  79. //
  80. PERF_COUNTER PerfCounter[NUM_PERF_COUNTERS];
  81. //
  82. // Number of cycles for a PERF_ENTRY and PERF_EXIT
  83. //
  84. static LARGE_INTEGER PerfEntryExitCycles;
  85. //
  86. // Number of cycles per second
  87. //
  88. static LARGE_INTEGER PerfCyclesPerSecond;
  89. //
  90. // The resolution of the NT-supplied performance
  91. // counter
  92. //
  93. static LARGE_INTEGER PerfFreq;
  94. #endif
  95. //----------------------------------------------------------------------
  96. //
  97. // InitPerfCounters
  98. //
  99. // This function initializes the performance counter statistic
  100. // array, estimates how many cycles on this processor equal a second,
  101. // and determines how many cycles it takes to execute a
  102. // PERF_ENTRY/PERF_EXIT pair.
  103. //
  104. //----------------------------------------------------------------------
  105. VOID
  106. InitPerfCounters()
  107. {
  108. #if PERFORMANCE
  109. volatile ULONG i;
  110. LARGE_INTEGER calStart;
  111. LARGE_INTEGER calEnd;
  112. LARGE_INTEGER perfStart, perfEnd;
  113. LARGE_INTEGER seconds;
  114. KIRQL prevIrql;
  115. //
  116. // Number of calibration loops
  117. //
  118. #define CALIBRATION_LOOPS 500000
  119. //
  120. // This define is for a dummy performance counter that we
  121. // use just to calibrate the performance macro overhead
  122. //
  123. #define TEST 0
  124. //
  125. // Calibrate the overhead of PERF_ENTRY and PERF_EXIT, so that
  126. // they can be subtracted from the output
  127. //
  128. DbgDump(DBG_INIT, ("CALIBRATING PEFORMANCE TIMER....\n"));
  129. KeRaiseIrql( DISPATCH_LEVEL, &prevIrql );
  130. perfStart = KeQueryPerformanceCounter( &PerfFreq );
  131. RDTSC(calStart);
  132. for( i = 0; i < CALIBRATION_LOOPS; i++ ) {
  133. PERF_ENTRY(TEST);
  134. PERF_EXIT(TEST);
  135. }
  136. RDTSC(calEnd);
  137. perfEnd = KeQueryPerformanceCounter(NULL);
  138. KeLowerIrql( prevIrql );
  139. //
  140. // Calculate the cycles/PERF_ENTRY, and the number of cycles/second
  141. //
  142. PerfEntryExitCycles.QuadPart = (calEnd.QuadPart - calStart.QuadPart)/CALIBRATION_LOOPS;
  143. seconds.QuadPart = ((perfEnd.QuadPart - perfStart.QuadPart) * 1000 )/ PerfFreq.QuadPart;
  144. PerfCyclesPerSecond.QuadPart =
  145. seconds.QuadPart ? ((calEnd.QuadPart - calStart.QuadPart) * 1000) / seconds.QuadPart : 0;
  146. DbgDump(DBG_INIT, ("Machine's Cycles Per Second : %I64d\n", PerfCyclesPerSecond.QuadPart ));
  147. DbgDump(DBG_INIT, ("Machine's Cycles in PERF_XXXX : %I64d\n", PerfEntryExitCycles.QuadPart ));
  148. DbgDump(DBG_INIT, ("Machine's NT Performance counter frequency: %I64d\n", PerfFreq.QuadPart ));
  149. //
  150. // Initialize the array
  151. //
  152. for( i = 0; i < NUM_PERF_COUNTERS; i++ ) {
  153. PerfCounter[i].Count = 0;
  154. KeInitializeSpinLock( &PerfCounter[i].Lock );
  155. PerfCounter[i].TotalCycles.QuadPart = 0;
  156. }
  157. #endif
  158. }
  159. // *******************************************************************
  160. // Name:
  161. // DumpPerfCounters()
  162. //
  163. // Description:
  164. // Dumps the performance counters
  165. //
  166. // Assumptions:
  167. //
  168. // Returns:
  169. //
  170. // *******************************************************************
  171. VOID
  172. DumpPerfCounters()
  173. {
  174. #if PERFORMANCE
  175. int i;
  176. LARGE_INTEGER totCycles;
  177. LARGE_INTEGER totLengthMs;
  178. LARGE_INTEGER avgLengthMs;
  179. if (DebugLevel & DBG_PERF ) {
  180. PerfPrint(("\n"));
  181. PerfPrint(("Machine's Cycles Per Second : %I64d\n", PerfCyclesPerSecond.QuadPart ));
  182. PerfPrint(("Machine's Cycles in PERF_XXXX : %I64d\n", PerfEntryExitCycles.QuadPart ));
  183. PerfPrint(("Machine's NT Performance counter frequency: %I64d\n", PerfFreq.QuadPart ));
  184. PerfPrint(("\n===================================================================================\n"));
  185. PerfPrint((" %-30s Count TTL Time Avg Time (uS)\n", "Function" ));
  186. PerfPrint(("===================================================================================\n"));
  187. for( i = 0; i < NUM_PERF_COUNTERS; i++ ) {
  188. totCycles = PerfCounter[i].TotalCycles;
  189. totCycles.QuadPart -= (PerfCounter[i].Count * PerfEntryExitCycles.QuadPart);
  190. totLengthMs.QuadPart = PerfCyclesPerSecond.QuadPart ? (totCycles.QuadPart * 1000000)/
  191. PerfCyclesPerSecond.QuadPart : 0;
  192. avgLengthMs.QuadPart = PerfCounter[i].Count ? totLengthMs.QuadPart / PerfCounter[i].Count : 0;
  193. PerfPrint((" %-30s %10d %15I64d %14I64d\n",
  194. CounterNames[i], PerfCounter[i].Count,
  195. totLengthMs.QuadPart, avgLengthMs.QuadPart ));
  196. /*
  197. PerfPrint((" %-30s %10s %15I64d %14I64d (CY)\n",
  198. "", "",
  199. totCycles.QuadPart,
  200. totCycles.QuadPart ? totCycles.QuadPart / PerfCounter[i].Count: 0 ));
  201. PerfPrint(("------------------------------------------------------------------------------\n"));
  202. */
  203. }
  204. PerfPrint(("------------------------------------------------------------------------------\n"));
  205. }
  206. #endif
  207. }