hvdebtim.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:18k
源码类别:

Symbian

开发平台:

Visual C++

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