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.

292 lines
8.3 KiB

  1. /******************************************************************************
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. Perf.cpp
  5. Abstract:
  6. This file contains debugging stuff.
  7. Revision History:
  8. Davide Massarenti (dmassare) 01/17/2000
  9. created
  10. ******************************************************************************/
  11. #include "stdafx.h"
  12. ////////////////////////////////////////////////////////////////////////////////
  13. #ifdef HSS_PERFORMANCEDUMP
  14. #include <ProjectConstants.h>
  15. #include <MPC_utils.h>
  16. ////////////////////////////////////////////////////////////////////////////////
  17. class PerfLog
  18. {
  19. public:
  20. MPC::string szText;
  21. LARGE_INTEGER liTime;
  22. DWORDLONG ullTotal;
  23. };
  24. typedef std::list< PerfLog > PerfResults;
  25. typedef PerfResults::iterator PerfResultsIter;
  26. typedef PerfResults::const_iterator PerfResultsIterConst;
  27. ////////////////////////////////////////////////////////////////////////////////
  28. static PerfResults s_lst;
  29. static LARGE_INTEGER s_liStartOfPerf;
  30. static LARGE_INTEGER s_liAdjust;
  31. static MPC::CComSafeAutoCriticalSection s_csec;
  32. ////////////////////////////////////////////////////////////////////////////////
  33. #define DEBUG_PERF_EVENTS DEBUG_PERF_EVENTS_IN | DEBUG_PERF_EVENTS_OUT
  34. static const MPC::StringToBitField s_arrMap[] =
  35. {
  36. { L"BASIC" , DEBUG_PERF_BASIC , DEBUG_PERF_BASIC , -1 },
  37. { L"PROTOCOL" , DEBUG_PERF_PROTOCOL , DEBUG_PERF_PROTOCOL , -1 },
  38. { L"PROTOCOL_READ", DEBUG_PERF_PROTOCOL_READ, DEBUG_PERF_PROTOCOL_READ, -1 },
  39. { L"MARS" , DEBUG_PERF_MARS , DEBUG_PERF_MARS , -1 },
  40. { L"EVENTS_IN" , DEBUG_PERF_EVENTS_IN , DEBUG_PERF_EVENTS_IN , -1 },
  41. { L"EVENTS_OUT" , DEBUG_PERF_EVENTS_OUT , DEBUG_PERF_EVENTS_OUT , -1 },
  42. { L"EVENTS" , DEBUG_PERF_EVENTS , DEBUG_PERF_EVENTS , -1 },
  43. { L"PROXIES" , DEBUG_PERF_PROXIES , DEBUG_PERF_PROXIES , -1 },
  44. { L"QUERIES" , DEBUG_PERF_QUERIES , DEBUG_PERF_QUERIES , -1 },
  45. { L"CACHE_L1" , DEBUG_PERF_CACHE_L1 , DEBUG_PERF_CACHE_L1 , -1 },
  46. { L"CACHE_L2" , DEBUG_PERF_CACHE_L2 , DEBUG_PERF_CACHE_L2 , -1 },
  47. { L"HELPSVC" , DEBUG_PERF_HELPSVC , DEBUG_PERF_HELPSVC , -1 },
  48. { L"HELPHOST" , DEBUG_PERF_HELPHOST , DEBUG_PERF_HELPHOST , -1 },
  49. { L"ALL" , -1 , -1 , -1 },
  50. { NULL }
  51. };
  52. static const WCHAR s_Key [] = HC_REGISTRY_BASE L"\\Perf";
  53. static const WCHAR s_Value[] = L"Mask";
  54. ////////////////////////////////////////////////////////////////////////////////
  55. static DWORD s_mode;
  56. static LARGE_INTEGER s_liEnter;
  57. static LARGE_INTEGER s_liExit;
  58. static CHAR s_rgLineA[4096];
  59. static WCHAR s_rgLineW[4096];
  60. static void StopCounter()
  61. {
  62. s_csec.Lock();
  63. ::QueryPerformanceCounter( &s_liEnter );
  64. if(s_liStartOfPerf.QuadPart == 0)
  65. {
  66. bool fFound;
  67. s_liStartOfPerf = s_liEnter;
  68. s_mode = DEBUG_PERF_BASIC;
  69. if(FAILED(MPC::RegKey_Value_Read( s_mode, fFound, s_Key, s_Value )) || fFound == false)
  70. {
  71. MPC::wstring szValue;
  72. if(SUCCEEDED(MPC::RegKey_Value_Read( szValue, fFound, s_Key, s_Value )) && fFound)
  73. {
  74. DWORD dwMode;
  75. if(SUCCEEDED(MPC::ConvertStringToBitField( szValue.c_str(), dwMode, s_arrMap, true )) && dwMode)
  76. {
  77. s_mode = dwMode;
  78. }
  79. }
  80. }
  81. }
  82. }
  83. static void RestartCounter()
  84. {
  85. ::QueryPerformanceCounter( &s_liExit );
  86. s_liAdjust.QuadPart += s_liExit.QuadPart - s_liEnter.QuadPart;
  87. s_csec.Unlock();
  88. }
  89. static void DEBUG_AppendPerf( LPCSTR szMessage )
  90. {
  91. PerfResultsIter it;
  92. DWORDLONG ullTotal = 0;
  93. {
  94. HANDLE pHeaps[256];
  95. DWORD dwNumberOfHeaps = ::GetProcessHeaps( ARRAYSIZE(pHeaps), pHeaps );
  96. for(DWORD i=0; i<dwNumberOfHeaps; i++)
  97. {
  98. PROCESS_HEAP_ENTRY entry; entry.lpData = NULL;
  99. while(::HeapWalk( pHeaps[i], &entry ))
  100. {
  101. if(entry.wFlags & PROCESS_HEAP_ENTRY_BUSY)
  102. {
  103. //
  104. // Allocated block. Add both it's size and its overhead to the total
  105. // We want the overhead since it figures into the total required
  106. // commitment.
  107. //
  108. ullTotal += (entry.cbData + entry.cbOverhead);
  109. }
  110. }
  111. }
  112. }
  113. it = s_lst.insert( s_lst.end() );
  114. it->szText = szMessage;
  115. it->liTime.QuadPart = s_liEnter.QuadPart - s_liStartOfPerf.QuadPart - s_liAdjust.QuadPart;
  116. it->ullTotal = ullTotal;
  117. }
  118. void DEBUG_AppendPerf( DWORD mode ,
  119. LPCSTR szMessageFmt ,
  120. ... )
  121. {
  122. StopCounter();
  123. if(mode & s_mode)
  124. {
  125. va_list arglist;
  126. int iLen;
  127. //
  128. // Format the log line.
  129. //
  130. va_start( arglist, szMessageFmt );
  131. iLen = _vsnprintf( s_rgLineA, MAXSTRLEN(s_rgLineA), szMessageFmt, arglist );
  132. va_end( arglist );
  133. //
  134. // Is the arglist too big for us?
  135. //
  136. if(iLen < 0)
  137. {
  138. iLen = MAXSTRLEN(s_rgLineA);
  139. }
  140. s_rgLineA[iLen] = 0;
  141. DEBUG_AppendPerf( s_rgLineA );
  142. }
  143. RestartCounter();
  144. }
  145. void DEBUG_AppendPerf( DWORD mode ,
  146. LPCWSTR szMessageFmt ,
  147. ... )
  148. {
  149. StopCounter();
  150. if(mode & s_mode)
  151. {
  152. USES_CONVERSION;
  153. va_list arglist;
  154. int iLen;
  155. //
  156. // Format the log line.
  157. //
  158. va_start( arglist, szMessageFmt );
  159. iLen = _vsnwprintf( s_rgLineW, MAXSTRLEN(s_rgLineW), szMessageFmt, arglist );
  160. va_end( arglist );
  161. //
  162. // Is the arglist too big for us?
  163. //
  164. if(iLen < 0)
  165. {
  166. iLen = MAXSTRLEN(s_rgLineW);
  167. }
  168. s_rgLineW[iLen] = 0;
  169. DEBUG_AppendPerf( W2A(s_rgLineW) );
  170. }
  171. RestartCounter();
  172. }
  173. void DEBUG_DumpPerf( LPCWSTR szFile )
  174. {
  175. HANDLE hFile;
  176. SYSTEMTIME st;
  177. DWORD dwWritten;
  178. LARGE_INTEGER liFreq;
  179. LARGE_INTEGER* pliPrev = NULL;
  180. MPC::wstring strFile = szFile; MPC::SubstituteEnvVariables( strFile );
  181. PerfResultsIter it;
  182. int len;
  183. double scale;
  184. ::QueryPerformanceFrequency( &liFreq ); scale = (double)liFreq.QuadPart / 1E6;
  185. //
  186. // Calc max entry length.
  187. //
  188. for(len=0,it=s_lst.begin(); it!=s_lst.end(); it++)
  189. {
  190. if(len < it->szText.size())
  191. {
  192. len = it->szText.size();
  193. }
  194. }
  195. hFile = ::CreateFileW( strFile.c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_FLAG_SEQUENTIAL_SCAN, NULL );
  196. if(hFile == INVALID_HANDLE_VALUE) goto end;
  197. ::SetFilePointer( hFile, 0, NULL, FILE_END );
  198. //
  199. // Prepend current time.
  200. //
  201. ::GetLocalTime( &st );
  202. sprintf( s_rgLineA, "Performance Dump: %04u/%02u/%02u %02u:%02u:%02u\n", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond );
  203. if(::WriteFile( hFile, s_rgLineA, strlen( s_rgLineA ), &dwWritten, NULL ) == FALSE) goto end;
  204. sprintf( s_rgLineA, "=====================================\n" );
  205. if(::WriteFile( hFile, s_rgLineA, strlen( s_rgLineA ), &dwWritten, NULL ) == FALSE) goto end;
  206. //
  207. // Dump all the entries.
  208. //
  209. for(it=s_lst.begin(); it!=s_lst.end(); )
  210. {
  211. PerfLog& pl = *it++;
  212. double t0 = (double)pl. liTime.QuadPart ;
  213. double dT = it != s_lst.end() ? ((double)it->liTime.QuadPart - t0) : 0;
  214. sprintf( s_rgLineA, "%-*s : %9ld us dT: %9ld us (Mem: %9ld)\n", len, pl.szText.c_str(), (long)(t0 / scale), (long)(dT / scale), (long)pl.ullTotal );
  215. if(::WriteFile( hFile, s_rgLineA, strlen( s_rgLineA ), &dwWritten, NULL ) == FALSE) goto end;
  216. }
  217. sprintf( s_rgLineA, "\n\n\n" );
  218. if(::WriteFile( hFile, s_rgLineA, strlen( s_rgLineA ), &dwWritten, NULL ) == FALSE) goto end;
  219. end:
  220. if(hFile != INVALID_HANDLE_VALUE) ::CloseHandle( hFile );
  221. }
  222. #endif