hvdebtim.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:17k
源码类别:

Symbian

开发平台:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 1.0/RPSL 1.0 
  3.  *  
  4.  * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
  5.  *      
  6.  * The contents of this file, and the files included with this file, are 
  7.  * subject to the current version of the RealNetworks Public Source License 
  8.  * Version 1.0 (the "RPSL") available at 
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed 
  10.  * the file under the RealNetworks Community Source License Version 1.0 
  11.  * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
  12.  * in which case the RCSL will apply. You may also obtain the license terms 
  13.  * directly from RealNetworks.  You may not use this file except in 
  14.  * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
  15.  * applicable to this file, the RCSL.  Please see the applicable RPSL or 
  16.  * RCSL for the rights, obligations and limitations governing use of the 
  17.  * contents of the file.  
  18.  *  
  19.  * This file is part of the Helix DNA Technology. RealNetworks is the 
  20.  * developer of the Original Code and owns the copyrights in the portions 
  21.  * it created. 
  22.  *  
  23.  * This file, and the files included with this file, is distributed and made 
  24.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  25.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  26.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
  27.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  28.  * 
  29.  * Technology Compatibility Kit Test Suite(s) Location: 
  30.  *    http://www.helixcommunity.org/content/tck 
  31.  * 
  32.  * Contributor(s): 
  33.  *  
  34.  * ***** END LICENSE BLOCK ***** */ 
  35. /////////////////////////////////////////////////////////////////////////////
  36. // CVvDebugTimer --
  37. /* How to use it: 
  38. in C (here local creation of struct)
  39. #include "hvdebtim.h"
  40. struct CVvDebugTimer * pDebTim = newCVvDebugTimer();
  41. ResetTime(pDebTim);//reset accu
  42. StartTime(pDebTim);
  43. Debugee();
  44. StopAndAccuTime(pDebTim);
  45. //AverageAndOutputAccuTime(pDebTim, "Resamp@22 kHz", 1);
  46. OutputAccuTime(pDebTim, "Resamp@22 kHz", 1);
  47. in C++:
  48. #include "hvdebtim.h"
  49. CVvDebugTimer DebTim01;
  50. CVvDebugTimer DebTim02;
  51. CVvDebugTimer DebTim03;
  52. DebTim01.StartTime();
  53. Debugee();
  54. DebTim01.StopAndAccuTime();
  55. //DebTim01.AverageAndOutputAccuTime("VvDecode", 1);
  56. DebTim01.OutputAccuTime("VvDecode  ", 1);
  57. DebTim01.ResetTime();//reset accu
  58. */
  59. #include <stdio.h>
  60. #include "hvutils.h"
  61. #include "hvdebtim.h"
  62. #include "hxstrutl.h"
  63. /********************************/
  64. /* time helper functions */
  65. extern "C" {
  66. #if TIMERTYPE!=WIN31_TIME
  67. static LARGE_INTEGER liFrequency = {0};
  68. static S32 nFrequencyValid = FREQUENCY_NOTMEASURED;
  69. #endif
  70. /********************************/
  71. void VvGetAbsCpuClocks(__int64 *time)
  72. {
  73. // _asm RdTsc ; Get count of cycles into EDX: EAX
  74. _asm {
  75. _emit 0x0F //0F 31 is RDTSC opcode: Reads Pentium CPU clock (costs only 6 clocks at Ring 0, 11 at Ring 3)
  76. _emit 0x31 //  into EDX:EAX
  77. mov ebx, time
  78. mov [ebx], eax;//Intel Little Endian
  79. mov [ebx+4], edx
  80. }
  81. }
  82. /********************************/
  83. void VvZeroAbsCpuClocks(void) //Force Pentium clock to 0  (Can be done at Ring 0 only)
  84. {
  85. _asm{
  86. mov ECX, 0x10 //Machine-specific register 10h is the Time Stamp Counter
  87. xor EAX,EAX //Timestamp we want to set goes
  88. xor EDX,EDX //  into EDX:EAX
  89. _emit 0x0F     //WRMSR opcode is 0F 30
  90. _emit 0x30
  91. }
  92. }
  93. /********************************/
  94. #define TOLERANCE 1 // Number of MHz to allow
  95. //   samplings to deviate from
  96. //   average of samplings.
  97. //   Initially set to 2.
  98. #define ROUND_THRESHOLD 6
  99. U32  GetRDTSCCpuSpeed()
  100. {
  101. unsigned long in_cycles=0; // Internal clock cycles during
  102. //   test
  103. unsigned long ex_ticks=0; // Microseconds elapsed during 
  104. //   test
  105. unsigned long raw_freq=0; // Raw frequency of CPU in MHz
  106. unsigned long norm_freq=0; // Normalized frequency of CPU
  107. LARGE_INTEGER t0,t1; // Variables for High-
  108. //   Resolution Performance
  109. //   Counter reads
  110. unsigned long  freq  =0; // Most current frequ. calculation
  111. unsigned long  freq2 =0; // 2nd most current frequ. calc.
  112. unsigned long  freq3 =0; // 3rd most current frequ. calc.
  113. unsigned long  total; // Sum of previous three frequency
  114. //   calculations
  115. int tries=0; // Number of times a calculation has
  116. //   been made on this call to 
  117. //   cpuspeed
  118. unsigned long   total_cycles=0, cycles; // Clock cycles elapsed 
  119. //   during test
  120. unsigned long   stamp0, stamp1; // Time Stamp Variable 
  121. //   for beginning and end 
  122. //   of test
  123. unsigned long   total_ticks=0, ticks; // Microseconds elapsed 
  124. //   during test
  125. LARGE_INTEGER count_freq; // High Resolution 
  126. //   Performance Counter 
  127. //   frequency
  128. #ifdef WIN32
  129. int iPriority;
  130. HANDLE hThread = GetCurrentThread();
  131. #endif // WIN32;
  132. if ( !QueryPerformanceFrequency ( &count_freq ) ) 
  133. return raw_freq;//return 0
  134. // On processors supporting the Read 
  135. //   Time Stamp opcode, compare elapsed
  136. //   time on the High-Resolution Counter
  137. //   with elapsed cycles on the Time 
  138. //   Stamp Register.
  139. do { // This do loop runs up to 20 times or
  140.     //   until the average of the previous 
  141.     //   three calculated frequencies is 
  142.     //   within 1 MHz of each of the 
  143.     //   individual calculated frequencies. 
  144. //   This resampling increases the 
  145. //   accuracy of the results since
  146. //   outside factors could affect this
  147. //   calculation
  148. tries++; // Increment number of times sampled
  149. //   on this call to cpuspeed
  150. freq3 = freq2; // Shift frequencies back to make
  151. freq2 = freq; //   room for new frequency 
  152. //   measurement
  153.      QueryPerformanceCounter(&t0);
  154.      // Get high-resolution performance 
  155.      //   counter time
  156. t1.LowPart = t0.LowPart; // Set Initial time
  157. t1.HighPart = t0.HighPart;
  158. #ifdef WIN32
  159. iPriority = GetThreadPriority(hThread);
  160. if ( iPriority != THREAD_PRIORITY_ERROR_RETURN ) {
  161. SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL);
  162. }
  163. #endif // WIN32
  164.     while ( (unsigned long)t1.LowPart - (unsigned long)t0.LowPart<50) {   
  165.     // Loop until 50 ticks have 
  166.     //   passed since last read of hi-
  167. //  res counter. This accounts for
  168. //   overhead later.
  169. QueryPerformanceCounter(&t1);
  170. __asm {
  171. _emit 0x0F //0F 31 is RDTSC opcode: Reads Pentium CPU clock (costs only 6 clocks at Ring 0, 11 at Ring 3)
  172. _emit 0x31 //  into EDX:EAX
  173. MOV stamp0, EAX
  174. }
  175. }
  176. t0.LowPart = t1.LowPart; // Reset Initial 
  177. t0.HighPart = t1.HighPart; //   Time
  178.     while ((unsigned long)t1.LowPart-(unsigned long)t0.LowPart<1000 ) {
  179.     // Loop until 1000 ticks have 
  180.     //   passed since last read of hi-
  181.     //   res counter. This allows for
  182. //   elapsed time for sampling.
  183.    
  184.     QueryPerformanceCounter(&t1);
  185.    
  186. __asm {
  187. _emit 0x0F //0F 31 is RDTSC opcode: Reads Pentium CPU clock (costs only 6 clocks at Ring 0, 11 at Ring 3)
  188. _emit 0x31 //  into EDX:EAX
  189. MOV stamp1, EAX
  190. }
  191. }
  192. #ifdef WIN32
  193. // Reset priority
  194. if ( iPriority != THREAD_PRIORITY_ERROR_RETURN ) {
  195. SetThreadPriority(hThread, iPriority);
  196. }
  197. #endif // WIN32
  198.         cycles = stamp1 - stamp0; // Number of internal 
  199.          //   clock cycles is 
  200.          //   difference between 
  201.          //   two time stamp 
  202.          //   readings.
  203.      ticks = (unsigned long) t1.LowPart - (unsigned long) t0.LowPart;
  204. // Number of external ticks is
  205. //   difference between two
  206. //   hi-res counter reads.
  207. // Note that some seemingly arbitrary mulitplies and
  208. //   divides are done below. This is to maintain a 
  209. //   high level of precision without truncating the 
  210. //   most significant data. According to what value 
  211. //   ITERATIIONS is set to, these multiplies and
  212. //   divides might need to be shifted for optimal
  213. //   precision.
  214. ticks = ticks * 100000;
  215. // Convert ticks to hundred
  216. //   thousandths of a tick
  217. ticks = ticks / ( count_freq.LowPart/10 );
  218. // Hundred Thousandths of a 
  219. //   Ticks / ( 10 ticks/second )
  220. //   = microseconds (us)
  221. total_ticks += ticks;
  222. total_cycles += cycles;
  223. if ( ticks%count_freq.LowPart > count_freq.LowPart/2 )
  224. ticks++; // Round up if necessary
  225. freq = cycles/ticks; // Cycles / us  = MHz
  226.         
  227.       if ( cycles%ticks > ticks/2 )
  228.         freq++; // Round up if necessary
  229.           
  230. total = ( freq + freq2 + freq3 );
  231. // Total last three frequency 
  232. //   calculations
  233. } while ( (tries < 3 ) || 
  234.           (tries < 20)&&
  235.           ((abs(3 * freq -total) > 3*TOLERANCE )||
  236.            (abs(3 * freq2-total) > 3*TOLERANCE )||
  237.            (abs(3 * freq3-total) > 3*TOLERANCE )));
  238. // Compare last three calculations to 
  239.            //   average of last three calculations.
  240. // Try one more significant digit.
  241. freq3 = ( total_cycles * 10 ) / total_ticks;
  242. freq2 = ( total_cycles * 100 ) / total_ticks;
  243. if ( freq2 - (freq3 * 10) >= ROUND_THRESHOLD )
  244. freq3++;
  245. raw_freq = total_cycles / total_ticks;
  246. norm_freq = raw_freq;
  247. freq = raw_freq * 10;
  248. if( (freq3 - freq) >= ROUND_THRESHOLD )
  249. norm_freq++;
  250. ex_ticks = total_ticks;
  251. in_cycles = total_cycles;
  252. return raw_freq*1000000;
  253. }
  254. /********************************/
  255. void MeasureFrequency()
  256. {
  257. nFrequencyValid = FREQUENCY_VALID;
  258. #if TIMERTYPE==WIN31_TIME
  259. liFrequency.QuadPart = 1000;//Ticks per second
  260. #elif TIMERTYPE==WIN95_TIME
  261. LARGE_INTEGER liPerfFreq;
  262. if(QueryPerformanceFrequency(&liPerfFreq)) {
  263. liFrequency = liPerfFreq.QuadPart;
  264. } else {
  265. nFrequencyValid = FREQUENCY_NOTVALID;
  266. }
  267. #elif TIMERTYPE==PENT_TIME
  268. liFrequency.QuadPart = GetRDTSCCpuSpeed();
  269. if(liFrequency.QuadPart==0) {
  270. nFrequencyValid = FREQUENCY_NOTVALID;
  271. }
  272. #endif
  273. }
  274. }
  275. /********************************/
  276. /* this is for cpp */
  277. CVvDebugTimer::CVvDebugTimer() {
  278. ResetTime();
  279. qwAverageAccuCount = 0;
  280. nSkipToNextOutput = 0;
  281. nDeltaHistoryPtr = 0;
  282. if(nFrequencyValid==FREQUENCY_NOTMEASURED) {
  283. MeasureFrequency();
  284. }
  285. }
  286. void CVvDebugTimer::ResetTime() {
  287. qwAccuCount = 0;
  288. qwDeltaCount = 0;
  289. }
  290. /*************************/
  291. void CVvDebugTimer::StartTime() {
  292. #if TIMERTYPE==WIN31_TIME
  293. dwStartCount = GetTickCount();
  294. #elif TIMERTYPE==WIN95_TIME
  295. QueryPerformanceCounter(&liStartCount);
  296. #elif TIMERTYPE==PENT_TIME
  297. VvGetAbsCpuClocks(&(liStartCount.QuadPart));
  298. #endif
  299. }
  300.     
  301. /*************************/
  302. void CVvDebugTimer::StopAndAccuTime() {
  303. #if TIMERTYPE==WIN31_TIME
  304. dwStopCount = GetTickCount();
  305. qwDeltaCount = (__int64) dwStopCount - (__int64) dwStartCount;
  306. #else
  307. #if TIMERTYPE==WIN95_TIME
  308. QueryPerformanceCounter(&liStopCount);
  309. #elif TIMERTYPE==PENT_TIME
  310. VvGetAbsCpuClocks(&(liStopCount.QuadPart));
  311. #endif
  312. qwDeltaCount = ((__int64)liStopCount.QuadPart  
  313. -(__int64)liStartCount.QuadPart);
  314. #if TIMERTYPE==PENT_TIME
  315. /* magig number, assume that function calls etc. cost 160 cycles */
  316. qwDeltaCount -= 160;
  317. #endif
  318. #endif
  319. qwDeltaHistory[nDeltaHistoryPtr] = qwDeltaCount;
  320. nDeltaHistoryPtr++;
  321. if(nDeltaHistoryPtr >= NBDELTASHISTORY) 
  322. nDeltaHistoryPtr = 0;
  323. qwAccuCount += qwDeltaCount;
  324. }
  325. /*************************/
  326. void CVvDebugTimer::OutputDeltaTime(char *pcLabel, S32 nMaxSkip) {
  327. char string[80]; /* Flawfinder: ignore */
  328. nSkipToNextOutput++;//only every nMaxSkip time 
  329. if(nSkipToNextOutput >= nMaxSkip) {
  330. nSkipToNextOutput = 0;
  331. #if TIMERTYPE==WIN31_TIME
  332. SafeSprintf(string, 80,"W31%s: %7.2lf msn", pcLabel, (double) qwDeltaCount);
  333. #else
  334. if(nFrequencyValid!=FREQUENCY_VALID) {
  335. SafeSprintf(string, 80,"%s: %7.2lf msn", pcLabel, 
  336. 1000.*(double)qwDeltaCount/(double) liFrequency.QuadPart);
  337. } else {
  338. SafeSprintf(string, 80,"%s: Frequency not validn", pcLabel);
  339. }
  340. #endif
  341. OutputDebugString(string);
  342. }
  343. }
  344. /*************************/
  345. int CVvDebugTimer::GetAccuTime(double *ptime) {
  346. int result;
  347. #if TIMERTYPE==WIN31_TIME
  348. *time = (double)qwAccuCount;
  349. result = 1
  350. #else
  351. if(nFrequencyValid == FREQUENCY_VALID) {
  352. *ptime = 1000.*(double)qwAccuCount/((double) liFrequency.QuadPart);
  353. result = 2;
  354. } else {
  355. *ptime = 0;
  356. result = 0;
  357. }
  358. #endif
  359. return(result);
  360. }
  361. /*************************/
  362. void CVvDebugTimer::OutputAccuTime(char *pcLabel, S32 nMaxSkip) {
  363. // we run through it only every nMaxSkip times
  364. char string[80]; /* Flawfinder: ignore */
  365. nSkipToNextOutput++;//only every nMaxSkip time 
  366. if(nSkipToNextOutput >= nMaxSkip) {
  367. nSkipToNextOutput = 0;
  368. double time;
  369. int result;
  370. result = GetAccuTime(&time);
  371. if(result==1) {
  372. SafeSprintf(string, 80, "W31%s: %7.2lf msn", pcLabel, time);
  373. } else if(result==2) {
  374. SafeSprintf(string, 80, "%s: %7.2lf msn", pcLabel, time);
  375. } else {
  376. SafeSprintf(string, 80,"%s: QueryPerformanceFrequency not supportedn", pcLabel);
  377. }
  378. OutputDebugString(string);
  379. }
  380. }
  381. /*************************/
  382. void CVvDebugTimer::LogAccuTime(char *pcLabel, S32 nMaxSkip) {
  383. // we run through it only every nMaxSkip times
  384. char string[80]; /* Flawfinder: ignore */
  385. nSkipToNextOutput++;//only every nMaxSkip time 
  386. if(nSkipToNextOutput >= nMaxSkip) {
  387. nSkipToNextOutput = 0;
  388. #if TIMERTYPE==WIN31_TIME
  389. SafeSprintf(string, 80, "W31%s: %7.2lf msn", pcLabel, 
  390. (double)qwAccuCount);
  391. #else
  392. if(nFrequencyValid == FREQUENCY_VALID) {
  393. SafeSprintf(string, 80,"%s: %7.2lf msn", pcLabel, 
  394. 1000.*(double)qwAccuCount/((double) liFrequency.QuadPart));
  395. } else {
  396. SafeSprintf(string, 80,"%s: QueryPerformanceFrequency not supportedn", pcLabel);
  397. }
  398. #endif
  399. dprintf(string);
  400. }
  401. }
  402. #define VVDEBUGOUT(pcOut, string, nbMaxChar)  
  403. if(pcOut) { (strncpy(pcOut, string, nbMaxChar)); } else {(OutputDebugString(string));} /* Flawfinder: ignore */
  404. /*************************/
  405. void CVvDebugTimer::AverageAndOutputAccuTime(char *pcLabel, S32 nMaxSkip, 
  406.  char *pcOut=0, S32 nbMaxChar=0) {
  407. // we run through it only every nMaxSkip times
  408. char string[800]; /* Flawfinder: ignore */
  409. qwAverageAccuCount += qwAccuCount;
  410. nSkipToNextOutput++;//only every nMaxSkip time 
  411. if(nSkipToNextOutput >= nMaxSkip) {
  412. #if TIMERTYPE==WIN31_TIME
  413. SafeSprintf(string, 800, "W31%s: %7.2lf msn", pcLabel, 
  414. (double)qwAverageAccuCount/(double) nSkipToNextOutput);
  415. #else
  416. if(nFrequencyValid == FREQUENCY_VALID) {
  417. S32 ii;
  418. char appendix[20]; /* Flawfinder: ignore */
  419. sprintf(string, "("); /* Flawfinder: ignore */
  420. for(ii=0; ii<nDeltaHistoryPtr; ii++) {
  421. SafeSprintf(appendix, 20,"%3.1lf ", 
  422. 1000.*(double)qwDeltaHistory[ii]/
  423. ((double) liFrequency.QuadPart));
  424. SafeStrCat(string,  appendix, 800);
  425. }
  426. SafeStrCat(string,  ")n", 800);
  427. VVDEBUGOUT(pcOut, string, nbMaxChar);
  428. SafeSprintf(string, 800,"%s: %7.2lf msn", pcLabel, 
  429. 1000.*(double)qwAverageAccuCount
  430. /((double) liFrequency.LowPart + 4294967296.*liFrequency.HighPart)
  431. /(double) nSkipToNextOutput);
  432. VVDEBUGOUT(pcOut, string, nbMaxChar);
  433. } else {
  434. SafeSprintf(string, 800,"%s: QueryPerformanceFrequency not supportedn", pcLabel);
  435. VVDEBUGOUT(pcOut, string, nbMaxChar);
  436. }
  437. #endif
  438. qwAverageAccuCount = 0;
  439. nSkipToNextOutput = 0;
  440. nDeltaHistoryPtr = 0;
  441. }
  442. }
  443. /********************************/
  444. /* this is for c interface */
  445. extern "C" {
  446.     //  external member functions
  447. void ResetTime(CVvDebugTimer *p) {
  448. p->qwAccuCount = 0;
  449. p->qwDeltaCount = 0;
  450. }
  451. // ctors, dtors, etc.
  452.     CVvDebugTimer * newCVvDebugTimer () {
  453. CVvDebugTimer *Tim; 
  454. Tim = new CVvDebugTimer;
  455. Tim->ResetTime();
  456. Tim->qwAverageAccuCount = 0;
  457. Tim->nSkipToNextOutput = 0;
  458. if(nFrequencyValid==FREQUENCY_NOTMEASURED) {
  459. MeasureFrequency();
  460. }
  461. return Tim;
  462. }
  463. void AverageAndOutputAccuTime(CVvDebugTimer *p, char *pcLabel, S32 nMaxSkip) {
  464. if(p) 
  465. p->AverageAndOutputAccuTime(pcLabel, nMaxSkip, 0, 0);
  466. }
  467. void AverageAndOutputAccuTimeString(CVvDebugTimer *p, char *pcLabel, S32 nMaxSkip,
  468. char *pcOut=0, S32 nbMaxChar=0) {
  469. if(p) 
  470. p->AverageAndOutputAccuTime(pcLabel, nMaxSkip, pcOut, nbMaxChar);
  471. }
  472. int GetAccuTime(CVvDebugTimer *p, double *ptime) {
  473. int result=0;
  474. *ptime = 0.;
  475. if(p) 
  476. result = p->GetAccuTime(ptime);
  477. return(result);
  478. }
  479. void OutputAccuTime(CVvDebugTimer *p, char *pcLabel, S32 nMaxSkip) {
  480. if(p) 
  481. p->OutputAccuTime(pcLabel, nMaxSkip);
  482. }
  483. void LogAccuTime(CVvDebugTimer *p, char *pcLabel, S32 nMaxSkip) {
  484. if(p) 
  485. p->LogAccuTime(pcLabel, nMaxSkip);
  486. }
  487. void OutputDeltaTime(CVvDebugTimer *p, char *pcLabel, S32 nMaxSkip) {
  488. if(p) 
  489. p->OutputDeltaTime(pcLabel, nMaxSkip);
  490. }
  491. void StopAndAccuTime(CVvDebugTimer *p) {
  492. if(p) 
  493. p->StopAndAccuTime();
  494. }
  495. void StartTime(CVvDebugTimer *p) {
  496. if(p) 
  497. p->StartTime();
  498. }
  499. }