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.

587 lines
15 KiB

  1. //------------------------------------------------------------------------
  2. //
  3. // File: shell\themes\test\ctlperf\Perflog.cpp
  4. //
  5. // Contents: Implementation of the Timing and logging class.
  6. //
  7. // Classes: CPerfLog
  8. //
  9. //------------------------------------------------------------------------
  10. #include "stdafx.h"
  11. #include "PerfLog.h"
  12. //+-----------------------------------------------------------------------
  13. //
  14. // Member: CPerfLog::CPerfLog
  15. //
  16. // Synopsis: Constructor
  17. //
  18. //------------------------------------------------------------------------
  19. CPerfLog::CPerfLog()
  20. {
  21. ::QueryPerformanceFrequency( (LARGE_INTEGER*) &m_liFreq);
  22. m_szPass1[0] = _T('\0');
  23. m_szPass2[0] = _T('\0');
  24. m_bLogging = false;
  25. m_nFramePaintTime = 0;
  26. m_nFrameResizeTime = 0;
  27. m_nFrameResizeAndPaintTime = 0;
  28. m_bFrame = false;
  29. m_bTwoPasses = false;
  30. m_rgnResults1 = NULL;
  31. m_rgnResults2 = NULL;
  32. m_rgszResults = NULL;
  33. m_cnResults1 = 0;
  34. m_cnResults2 = 0;
  35. m_cszResults = 0;
  36. m_bFirstPass = true;
  37. m_flLogFile = NULL;
  38. m_bNumberOnly = false;
  39. }
  40. //+-----------------------------------------------------------------------
  41. //
  42. // Member: CPerfLog::~CPerfLog
  43. //
  44. // Synopsis: Destructor
  45. //
  46. //------------------------------------------------------------------------
  47. CPerfLog::~CPerfLog()
  48. {
  49. StopLogging(); // Just in case the caller didn't call it
  50. }
  51. //+-----------------------------------------------------------------------
  52. //
  53. // Member: CPerfLog::StartLoggingOnePass
  54. //
  55. // Synopsis: Initialization method when loggin one pass
  56. //
  57. // Arguments: szFileName Name of the log file
  58. // hWndStatusBar Handle to a status bar window to receive info
  59. // szPass Name of the test
  60. //
  61. //------------------------------------------------------------------------
  62. void CPerfLog::StartLoggingOnePass(LPCTSTR szFileName, HWND hWndStatusBar, LPCTSTR szPass)
  63. {
  64. if (m_bLogging)
  65. {
  66. StopLogging();
  67. }
  68. if (m_liFreq == 0) // We can't do anything without it
  69. {
  70. m_bLogging = false;
  71. return;
  72. }
  73. if (szFileName)
  74. {
  75. _tcscpy(m_szFileName, szFileName);
  76. }
  77. if(szPass)
  78. {
  79. _tcscpy(m_szPass1, szPass);
  80. }
  81. m_flLogFile = ::_wfopen(szFileName, _T("w"));
  82. ATLASSERT(m_flLogFile);
  83. if(m_flLogFile != NULL)
  84. {
  85. m_hWndStatusBar = hWndStatusBar;
  86. m_nFramePaintTime = 0;
  87. m_nFrameResizeTime = 0;
  88. m_nFrameResizeAndPaintTime = 0;
  89. m_bLogging = true;
  90. }
  91. }
  92. //+-----------------------------------------------------------------------
  93. //
  94. // Member: CPerfLog::StopLogging
  95. //
  96. // Synopsis: Close and cleanup
  97. //
  98. //------------------------------------------------------------------------
  99. void CPerfLog::StopLogging()
  100. {
  101. if (m_flLogFile && ::ftell(m_flLogFile) != -1)
  102. {
  103. ::fflush(m_flLogFile);
  104. ::fclose(m_flLogFile);
  105. m_flLogFile = NULL;
  106. }
  107. if (m_rgnResults1)
  108. {
  109. free(m_rgnResults1);
  110. m_rgnResults1 = NULL;
  111. m_cnResults1 = 0;
  112. }
  113. if (m_rgnResults2)
  114. {
  115. free(m_rgnResults2);
  116. m_rgnResults2 = NULL;
  117. m_cnResults2 = 0;
  118. }
  119. if (m_cszResults)
  120. {
  121. for (UINT i = 0; i < m_cszResults; i++)
  122. free(m_rgszResults[i]);
  123. free(m_rgszResults);
  124. m_rgszResults = NULL;
  125. m_cszResults = 0;
  126. }
  127. m_bLogging = false;
  128. }
  129. //+-----------------------------------------------------------------------
  130. //
  131. // Member: CPerfLog::StartLoggingTwoPasses
  132. //
  133. // Synopsis: Initialization method when loggin two passes
  134. //
  135. // Arguments: szFileName Name of the log file
  136. // hWndStatusBar Handle to a status bar window to receive info
  137. // szPass1 Name of the first test
  138. // szPass2 Name of the second test
  139. //
  140. //------------------------------------------------------------------------
  141. void CPerfLog::StartLoggingTwoPasses(LPCTSTR szFileName, HWND hWndStatusBar, LPCTSTR szPass1, LPCTSTR szPass2)
  142. {
  143. m_bTwoPasses = true;
  144. StartLoggingOnePass(szFileName, hWndStatusBar, NULL); // Reuse main initialization (dirty)
  145. if (szPass1)
  146. {
  147. _tcscpy(m_szPass1, szPass1);
  148. }
  149. if (szPass2)
  150. {
  151. _tcscpy(m_szPass2, szPass2);
  152. }
  153. }
  154. //+-----------------------------------------------------------------------
  155. //
  156. // Member: CPerfLog::StopLoggingPass1
  157. //
  158. // Synopsis: For parity, does nothing
  159. //
  160. //------------------------------------------------------------------------
  161. void CPerfLog::StopLoggingPass1()
  162. {
  163. }
  164. //+-----------------------------------------------------------------------
  165. //
  166. // Member: CPerfLog::StartLoggingPass2
  167. //
  168. // Synopsis: Log pass 2
  169. //
  170. //------------------------------------------------------------------------
  171. void CPerfLog::StartLoggingPass2()
  172. {
  173. // Reset variables from pass 1
  174. m_nFramePaintTime = 0;
  175. m_nFrameResizeTime = 0;
  176. m_nFrameResizeAndPaintTime = 0;
  177. m_bFirstPass = false;
  178. }
  179. //+-----------------------------------------------------------------------
  180. //
  181. // Member: CPerfLog::StopLoggingPass2
  182. //
  183. // Synopsis: Close pass 2, output log and cleanup
  184. //
  185. //------------------------------------------------------------------------
  186. void CPerfLog::StopLoggingPass2()
  187. {
  188. UINT iResults2 = 0;
  189. UINT iszResults1 = 0;
  190. for (UINT iResults1 = 0; iResults1 < m_cnResults1; iResults1++)
  191. {
  192. if (m_rgnResults1[iResults1] == -1) // This is a string
  193. {
  194. fputws(m_rgszResults[iszResults1++], m_flLogFile);
  195. }
  196. else // Two results to display on the same line
  197. {
  198. if (m_rgnResults1[iResults1])
  199. {
  200. // just remvoed one \t so that slow colum would line up.
  201. swprintf(m_szBuf,
  202. _T("%u\t\t%u\t%.2f\n"),
  203. m_rgnResults1[iResults1],
  204. m_rgnResults2[iResults2],
  205. (100.0f * float(m_rgnResults2[iResults2]) / float(m_rgnResults1[iResults1])) - 100.0f);
  206. }
  207. else
  208. {
  209. swprintf(m_szBuf, _T("%u\t\t%u\t\t0\n"), m_rgnResults1[iResults1], m_rgnResults2[iResults2]);
  210. }
  211. iResults2++;
  212. fputws(m_szBuf, m_flLogFile);
  213. }
  214. }
  215. StopLogging();
  216. }
  217. //+-----------------------------------------------------------------------
  218. //
  219. // Member: CPerfLog::LogString
  220. //
  221. // Synopsis: Stores the string in memory
  222. //
  223. // Arguments: sz String to log
  224. //
  225. //------------------------------------------------------------------------
  226. void CPerfLog::LogString(LPCTSTR sz)
  227. {
  228. if (!m_bTwoPasses)
  229. {
  230. fputws(sz, m_flLogFile);
  231. }
  232. else if (m_bFirstPass)
  233. {
  234. m_cszResults++;
  235. m_rgszResults = (LPTSTR*) realloc(m_rgszResults, m_cszResults * sizeof(LPTSTR));
  236. m_rgszResults[m_cszResults - 1] = _wcsdup(sz);
  237. m_cnResults1++;
  238. m_rgnResults1 = (UINT*) realloc(m_rgnResults1, m_cnResults1 * sizeof(UINT));
  239. // Since -1 is an illegal value for the results, we use it to mark a string
  240. m_rgnResults1[m_cnResults1 - 1] = -1;
  241. }
  242. }
  243. //+-----------------------------------------------------------------------
  244. //
  245. // Member: CPerfLog::OpenLoggingClass
  246. //
  247. // Synopsis: Start timing a new control class name for the following timing
  248. //
  249. // Arguments: szClassName Name of class (for logging only)
  250. //
  251. //------------------------------------------------------------------------
  252. void CPerfLog::OpenLoggingClass(LPCTSTR szClassName)
  253. {
  254. if (!m_bLogging)
  255. {
  256. return;
  257. }
  258. ::SendMessage(m_hWndStatusBar, SB_SIMPLE, TRUE, 0L);
  259. ::SendMessage(m_hWndStatusBar, SB_SETTEXT, (255 | SBT_NOBORDERS), (LPARAM) szClassName);
  260. // Class header in the file
  261. if (m_bTwoPasses)
  262. {
  263. // added number only check
  264. if(m_bNumberOnly)
  265. {
  266. swprintf(m_szBuf, _T("%.12s\t%s\t%% Slower\n"), m_szPass1, m_szPass2);
  267. }
  268. else
  269. {
  270. swprintf(m_szBuf, _T("%-23s\t%.12s\t%s\t%% Slower\n"), szClassName, m_szPass1, m_szPass2);
  271. }
  272. }
  273. else
  274. {
  275. // added number only check
  276. if(m_bNumberOnly)
  277. {
  278. swprintf(m_szBuf, _T("%-23s\n"), szClassName);
  279. }
  280. else
  281. {
  282. swprintf(m_szBuf, _T("%-23s\t%s\n"), szClassName, m_szPass1);
  283. }
  284. }
  285. LogString(m_szBuf);
  286. if (!m_bFrame && !_tcsicmp(szClassName, kszFrameWnd))
  287. {
  288. m_bFrame = true;
  289. }
  290. else
  291. {
  292. m_bFrame = false;
  293. }
  294. }
  295. //+-----------------------------------------------------------------------
  296. //
  297. // Member: CPerfLog::CloseLoggingClass
  298. //
  299. // Synopsis: Finished with this class
  300. //
  301. //------------------------------------------------------------------------
  302. void CPerfLog::CloseLoggingClass()
  303. {
  304. if (!m_bLogging)
  305. {
  306. return;
  307. }
  308. LogString(_T("\n"));
  309. ::SendMessage(m_hWndStatusBar, SB_SETTEXT, (255 | SBT_NOBORDERS), (LPARAM) _T(""));
  310. }
  311. //+-----------------------------------------------------------------------
  312. //
  313. // Member: CPerfLog::StartCreate
  314. //
  315. // Synopsis: Beginning timing creation test
  316. //
  317. // Arguments: cCtl Number of controls being created (for logging)
  318. //
  319. //------------------------------------------------------------------------
  320. void CPerfLog::StartCreate(UINT cCtl)
  321. {
  322. if (!m_bLogging)
  323. {
  324. return;
  325. }
  326. // added number only check
  327. if(!m_bNumberOnly)
  328. {
  329. swprintf(m_szBuf, _T("Creation(x%d)\t\t"), cCtl);
  330. LogString(m_szBuf);
  331. }
  332. ::QueryPerformanceCounter( (LARGE_INTEGER*) &m_liStart);
  333. }
  334. //+-----------------------------------------------------------------------
  335. //
  336. // Member: CPerfLog::StopCreate
  337. //
  338. // Synopsis: Finished timing creation test
  339. //
  340. //------------------------------------------------------------------------
  341. void CPerfLog::StopCreate()
  342. {
  343. if (!m_bLogging)
  344. {
  345. return;
  346. }
  347. ::QueryPerformanceCounter( (LARGE_INTEGER*) &m_liEnd);
  348. OutputData();
  349. }
  350. //+-----------------------------------------------------------------------
  351. //
  352. // Member: CPerfLog::StartPaint
  353. //
  354. // Synopsis: Beginning timing painting test
  355. //
  356. // Arguments: nTimes Number of loops executed (for logging)
  357. //
  358. //------------------------------------------------------------------------
  359. void CPerfLog::StartPaint(UINT nTimes)
  360. {
  361. if (!m_bLogging)
  362. {
  363. return;
  364. }
  365. // added number only check
  366. if(!m_bNumberOnly)
  367. {
  368. swprintf(m_szBuf, _T("Paint(x%d)\t\t"), nTimes);
  369. LogString(m_szBuf);
  370. }
  371. ::QueryPerformanceCounter( (LARGE_INTEGER*) &m_liStart);
  372. }
  373. //+-----------------------------------------------------------------------
  374. //
  375. // Member: CPerfLog::StopPaint
  376. //
  377. // Synopsis: Finished timing painting test
  378. //
  379. //------------------------------------------------------------------------
  380. void CPerfLog::StopPaint()
  381. {
  382. if (!m_bLogging)
  383. {
  384. return;
  385. }
  386. ::QueryPerformanceCounter( (LARGE_INTEGER*) &m_liEnd);
  387. if (m_nFramePaintTime > 0)
  388. {
  389. m_liEnd -= m_nFramePaintTime;
  390. }
  391. OutputData();
  392. if (m_bFrame)
  393. {
  394. ATLASSERT(m_nFramePaintTime == 0);
  395. m_nFramePaintTime = UINT(m_liEnd - m_liStart);
  396. }
  397. }
  398. //+-----------------------------------------------------------------------
  399. //
  400. // Member: CPerfLog::StartResize
  401. //
  402. // Synopsis: Beginning timing resizing test
  403. //
  404. // Arguments: nTimes Number of loops executed (for logging)
  405. //
  406. //------------------------------------------------------------------------
  407. void CPerfLog::StartResize(UINT nTimes)
  408. {
  409. if (!m_bLogging)
  410. {
  411. return;
  412. }
  413. // added number only check
  414. if(!m_bNumberOnly)
  415. {
  416. swprintf(m_szBuf, _T("Resize(x%d)\t\t"), nTimes);
  417. LogString(m_szBuf);
  418. }
  419. ::QueryPerformanceCounter( (LARGE_INTEGER*) &m_liStart);
  420. }
  421. //+-----------------------------------------------------------------------
  422. //
  423. // Member: CPerfLog::StopResize
  424. //
  425. // Synopsis: Finished timing resizing test
  426. //
  427. //------------------------------------------------------------------------
  428. void CPerfLog::StopResize()
  429. {
  430. if (!m_bLogging)
  431. {
  432. return;
  433. }
  434. ::QueryPerformanceCounter( (LARGE_INTEGER*) &m_liEnd);
  435. if (m_nFrameResizeTime > 0)
  436. {
  437. m_liEnd -= m_nFrameResizeTime;
  438. }
  439. OutputData();
  440. if (m_bFrame)
  441. {
  442. ATLASSERT(m_nFrameResizeTime == 0);
  443. m_nFrameResizeTime = UINT(m_liEnd - m_liStart);
  444. }
  445. }
  446. //+-----------------------------------------------------------------------
  447. //
  448. // Member: CPerfLog::StartResizeAndPaint
  449. //
  450. // Synopsis: Beginning timing resizing with painting test
  451. //
  452. // Arguments: nTimes Number of loops executed (for logging)
  453. //
  454. //------------------------------------------------------------------------
  455. void CPerfLog::StartResizeAndPaint(UINT nTimes)
  456. {
  457. if (!m_bLogging)
  458. {
  459. return;
  460. }
  461. // added number only check
  462. if(!m_bNumberOnly)
  463. {
  464. swprintf(m_szBuf, _T("Resize and paint(x%d)\t"), nTimes);
  465. LogString(m_szBuf);
  466. }
  467. ::QueryPerformanceCounter( (LARGE_INTEGER*) &m_liStart);
  468. }
  469. //+-----------------------------------------------------------------------
  470. //
  471. // Member: CPerfLog::StopResizeAndPaint
  472. //
  473. // Synopsis: Finished timing resizing with painting test
  474. //
  475. //------------------------------------------------------------------------
  476. void CPerfLog::StopResizeAndPaint()
  477. {
  478. if (!m_bLogging)
  479. {
  480. return;
  481. }
  482. ::QueryPerformanceCounter( (LARGE_INTEGER*) &m_liEnd);
  483. if (m_nFrameResizeAndPaintTime > 0)
  484. {
  485. m_liEnd -= m_nFrameResizeAndPaintTime;
  486. }
  487. OutputData();
  488. if (m_bFrame)
  489. {
  490. ATLASSERT(m_nFrameResizeAndPaintTime == 0);
  491. m_nFrameResizeAndPaintTime = UINT(m_liEnd - m_liStart);
  492. }
  493. }
  494. //+-----------------------------------------------------------------------
  495. //
  496. // Member: CPerfLog::OutputData
  497. //
  498. // Synopsis: Stores the data in one of the buffers
  499. //
  500. //------------------------------------------------------------------------
  501. void CPerfLog::OutputData()
  502. {
  503. if (m_liEnd < m_liStart) // In case nLoops is low, it can happen
  504. {
  505. m_liEnd = m_liStart;
  506. }
  507. UINT nData = UINT((1000.0 * double(m_liEnd - m_liStart)) / double(m_liFreq));
  508. if (!m_bTwoPasses)
  509. {
  510. fwprintf(m_flLogFile, _T("%u\n"), nData);
  511. }
  512. else
  513. {
  514. if (m_bFirstPass)
  515. {
  516. m_cnResults1++;
  517. m_rgnResults1 = (UINT*) realloc(m_rgnResults1, m_cnResults1 * sizeof(UINT));
  518. m_rgnResults1[m_cnResults1 - 1] = nData;
  519. }
  520. else
  521. {
  522. m_cnResults2++;
  523. m_rgnResults2 = (UINT*) realloc(m_rgnResults2, m_cnResults2 * sizeof(UINT));
  524. m_rgnResults2[m_cnResults2 - 1] = nData;
  525. }
  526. }
  527. }
  528. //+-----------------------------------------------------------------------
  529. //
  530. // Member: CPerfLog::SetOutputType
  531. //
  532. // Synopsis: Stores the output type (numbers only) for use later
  533. //
  534. //------------------------------------------------------------------------
  535. void CPerfLog::SetOutputType(LPTSTR szNumberOnly)
  536. {
  537. if(!_tcsicmp(szNumberOnly, _T("true")))
  538. {
  539. m_bNumberOnly = true;
  540. }
  541. }