hvdebtim.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:18k
- /* ***** BEGIN LICENSE BLOCK *****
- * Source last modified: $Id: hvdebtim.cpp,v 1.2.40.1 2004/07/09 01:56:06 hubbe Exp $
- *
- * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
- *
- * The contents of this file, and the files included with this file,
- * are subject to the current version of the RealNetworks Public
- * Source License (the "RPSL") available at
- * http://www.helixcommunity.org/content/rpsl unless you have licensed
- * the file under the current version of the RealNetworks Community
- * Source License (the "RCSL") available at
- * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
- * will apply. You may also obtain the license terms directly from
- * RealNetworks. You may not use this file except in compliance with
- * the RPSL or, if you have a valid RCSL with RealNetworks applicable
- * to this file, the RCSL. Please see the applicable RPSL or RCSL for
- * the rights, obligations and limitations governing use of the
- * contents of the file.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License Version 2 or later (the
- * "GPL") in which case the provisions of the GPL are applicable
- * instead of those above. If you wish to allow use of your version of
- * this file only under the terms of the GPL, and not to allow others
- * to use your version of this file under the terms of either the RPSL
- * or RCSL, indicate your decision by deleting the provisions above
- * and replace them with the notice and other provisions required by
- * the GPL. If you do not delete the provisions above, a recipient may
- * use your version of this file under the terms of any one of the
- * RPSL, the RCSL or the GPL.
- *
- * This file is part of the Helix DNA Technology. RealNetworks is the
- * developer of the Original Code and owns the copyrights in the
- * portions it created.
- *
- * This file, and the files included with this file, is distributed
- * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
- * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
- * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
- * ENJOYMENT OR NON-INFRINGEMENT.
- *
- * Technology Compatibility Kit Test Suite(s) Location:
- * http://www.helixcommunity.org/content/tck
- *
- * Contributor(s):
- *
- * ***** END LICENSE BLOCK ***** */
- /////////////////////////////////////////////////////////////////////////////
- // CVvDebugTimer --
- /* How to use it:
- in C (here local creation of struct)
- #include "hvdebtim.h"
- struct CVvDebugTimer * pDebTim = newCVvDebugTimer();
- ResetTime(pDebTim);//reset accu
- StartTime(pDebTim);
- Debugee();
- StopAndAccuTime(pDebTim);
- //AverageAndOutputAccuTime(pDebTim, "Resamp@22 kHz", 1);
- OutputAccuTime(pDebTim, "Resamp@22 kHz", 1);
- in C++:
- #include "hvdebtim.h"
- CVvDebugTimer DebTim01;
- CVvDebugTimer DebTim02;
- CVvDebugTimer DebTim03;
- DebTim01.StartTime();
- Debugee();
-
- DebTim01.StopAndAccuTime();
- //DebTim01.AverageAndOutputAccuTime("VvDecode", 1);
- DebTim01.OutputAccuTime("VvDecode ", 1);
- DebTim01.ResetTime();//reset accu
- */
- #include <stdio.h>
- #include "hvutils.h"
- #include "hvdebtim.h"
- #include "hxstrutl.h"
- /********************************/
- /* time helper functions */
- extern "C" {
- #if TIMERTYPE!=WIN31_TIME
- static LARGE_INTEGER liFrequency = {0};
- static S32 nFrequencyValid = FREQUENCY_NOTMEASURED;
- #endif
- /********************************/
- void VvGetAbsCpuClocks(__int64 *time)
- {
- // _asm RdTsc ; Get count of cycles into EDX: EAX
- _asm {
- _emit 0x0F //0F 31 is RDTSC opcode: Reads Pentium CPU clock (costs only 6 clocks at Ring 0, 11 at Ring 3)
- _emit 0x31 // into EDX:EAX
- mov ebx, time
- mov [ebx], eax;//Intel Little Endian
- mov [ebx+4], edx
- }
- }
- /********************************/
- void VvZeroAbsCpuClocks(void) //Force Pentium clock to 0 (Can be done at Ring 0 only)
- {
- _asm{
- mov ECX, 0x10 //Machine-specific register 10h is the Time Stamp Counter
- xor EAX,EAX //Timestamp we want to set goes
- xor EDX,EDX // into EDX:EAX
- _emit 0x0F //WRMSR opcode is 0F 30
- _emit 0x30
- }
-
- }
- /********************************/
- #define TOLERANCE 1 // Number of MHz to allow
- // samplings to deviate from
- // average of samplings.
- // Initially set to 2.
- #define ROUND_THRESHOLD 6
- U32 GetRDTSCCpuSpeed()
- {
- unsigned long in_cycles=0; // Internal clock cycles during
- // test
- unsigned long ex_ticks=0; // Microseconds elapsed during
- // test
- unsigned long raw_freq=0; // Raw frequency of CPU in MHz
- unsigned long norm_freq=0; // Normalized frequency of CPU
- LARGE_INTEGER t0,t1; // Variables for High-
- // Resolution Performance
- // Counter reads
- unsigned long freq =0; // Most current frequ. calculation
- unsigned long freq2 =0; // 2nd most current frequ. calc.
- unsigned long freq3 =0; // 3rd most current frequ. calc.
-
- unsigned long total; // Sum of previous three frequency
- // calculations
- int tries=0; // Number of times a calculation has
- // been made on this call to
- // cpuspeed
- unsigned long total_cycles=0, cycles; // Clock cycles elapsed
- // during test
-
- unsigned long stamp0, stamp1; // Time Stamp Variable
- // for beginning and end
- // of test
- unsigned long total_ticks=0, ticks; // Microseconds elapsed
- // during test
-
- LARGE_INTEGER count_freq; // High Resolution
- // Performance Counter
- // frequency
- #ifdef WIN32
- int iPriority;
- HANDLE hThread = GetCurrentThread();
- #endif // WIN32;
- if ( !QueryPerformanceFrequency ( &count_freq ) )
- return raw_freq;//return 0
-
- // On processors supporting the Read
- // Time Stamp opcode, compare elapsed
- // time on the High-Resolution Counter
- // with elapsed cycles on the Time
- // Stamp Register.
-
- do { // This do loop runs up to 20 times or
- // until the average of the previous
- // three calculated frequencies is
- // within 1 MHz of each of the
- // individual calculated frequencies.
- // This resampling increases the
- // accuracy of the results since
- // outside factors could affect this
- // calculation
-
- tries++; // Increment number of times sampled
- // on this call to cpuspeed
-
- freq3 = freq2; // Shift frequencies back to make
- freq2 = freq; // room for new frequency
- // measurement
- QueryPerformanceCounter(&t0);
- // Get high-resolution performance
- // counter time
-
- t1.LowPart = t0.LowPart; // Set Initial time
- t1.HighPart = t0.HighPart;
- #ifdef WIN32
- iPriority = GetThreadPriority(hThread);
- if ( iPriority != THREAD_PRIORITY_ERROR_RETURN ) {
- SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL);
- }
- #endif // WIN32
- while ( (unsigned long)t1.LowPart - (unsigned long)t0.LowPart<50) {
- // Loop until 50 ticks have
- // passed since last read of hi-
- // res counter. This accounts for
- // overhead later.
- QueryPerformanceCounter(&t1);
- __asm {
- _emit 0x0F //0F 31 is RDTSC opcode: Reads Pentium CPU clock (costs only 6 clocks at Ring 0, 11 at Ring 3)
- _emit 0x31 // into EDX:EAX
- MOV stamp0, EAX
- }
- }
-
-
- t0.LowPart = t1.LowPart; // Reset Initial
- t0.HighPart = t1.HighPart; // Time
- while ((unsigned long)t1.LowPart-(unsigned long)t0.LowPart<1000 ) {
- // Loop until 1000 ticks have
- // passed since last read of hi-
- // res counter. This allows for
- // elapsed time for sampling.
-
-
- QueryPerformanceCounter(&t1);
-
- __asm {
- _emit 0x0F //0F 31 is RDTSC opcode: Reads Pentium CPU clock (costs only 6 clocks at Ring 0, 11 at Ring 3)
- _emit 0x31 // into EDX:EAX
- MOV stamp1, EAX
- }
- }
-
- #ifdef WIN32
- // Reset priority
- if ( iPriority != THREAD_PRIORITY_ERROR_RETURN ) {
- SetThreadPriority(hThread, iPriority);
- }
- #endif // WIN32
- cycles = stamp1 - stamp0; // Number of internal
- // clock cycles is
- // difference between
- // two time stamp
- // readings.
- ticks = (unsigned long) t1.LowPart - (unsigned long) t0.LowPart;
- // Number of external ticks is
- // difference between two
- // hi-res counter reads.
-
- // Note that some seemingly arbitrary mulitplies and
- // divides are done below. This is to maintain a
- // high level of precision without truncating the
- // most significant data. According to what value
- // ITERATIIONS is set to, these multiplies and
- // divides might need to be shifted for optimal
- // precision.
- ticks = ticks * 100000;
- // Convert ticks to hundred
- // thousandths of a tick
-
- ticks = ticks / ( count_freq.LowPart/10 );
- // Hundred Thousandths of a
- // Ticks / ( 10 ticks/second )
- // = microseconds (us)
- total_ticks += ticks;
- total_cycles += cycles;
- if ( ticks%count_freq.LowPart > count_freq.LowPart/2 )
- ticks++; // Round up if necessary
-
- freq = cycles/ticks; // Cycles / us = MHz
-
- if ( cycles%ticks > ticks/2 )
- freq++; // Round up if necessary
-
- total = ( freq + freq2 + freq3 );
- // Total last three frequency
- // calculations
- } while ( (tries < 3 ) ||
- (tries < 20)&&
- ((abs(3 * freq -total) > 3*TOLERANCE )||
- (abs(3 * freq2-total) > 3*TOLERANCE )||
- (abs(3 * freq3-total) > 3*TOLERANCE )));
- // Compare last three calculations to
- // average of last three calculations.
- // Try one more significant digit.
- freq3 = ( total_cycles * 10 ) / total_ticks;
- freq2 = ( total_cycles * 100 ) / total_ticks;
- if ( freq2 - (freq3 * 10) >= ROUND_THRESHOLD )
- freq3++;
- raw_freq = total_cycles / total_ticks;
- norm_freq = raw_freq;
- freq = raw_freq * 10;
- if( (freq3 - freq) >= ROUND_THRESHOLD )
- norm_freq++;
- ex_ticks = total_ticks;
- in_cycles = total_cycles;
- return raw_freq*1000000;
- }
- /********************************/
- void MeasureFrequency()
- {
- nFrequencyValid = FREQUENCY_VALID;
- #if TIMERTYPE==WIN31_TIME
- liFrequency.QuadPart = 1000;//Ticks per second
- #elif TIMERTYPE==WIN95_TIME
- LARGE_INTEGER liPerfFreq;
- if(QueryPerformanceFrequency(&liPerfFreq)) {
- liFrequency = liPerfFreq.QuadPart;
- } else {
- nFrequencyValid = FREQUENCY_NOTVALID;
- }
- #elif TIMERTYPE==PENT_TIME
- liFrequency.QuadPart = GetRDTSCCpuSpeed();
- if(liFrequency.QuadPart==0) {
- nFrequencyValid = FREQUENCY_NOTVALID;
- }
- #endif
- }
- }
- /********************************/
- /* this is for cpp */
- CVvDebugTimer::CVvDebugTimer() {
- ResetTime();
- qwAverageAccuCount = 0;
- nSkipToNextOutput = 0;
- nDeltaHistoryPtr = 0;
- if(nFrequencyValid==FREQUENCY_NOTMEASURED) {
- MeasureFrequency();
- }
- }
- void CVvDebugTimer::ResetTime() {
- qwAccuCount = 0;
- qwDeltaCount = 0;
-
- }
- /*************************/
- void CVvDebugTimer::StartTime() {
- #if TIMERTYPE==WIN31_TIME
- dwStartCount = GetTickCount();
- #elif TIMERTYPE==WIN95_TIME
- QueryPerformanceCounter(&liStartCount);
- #elif TIMERTYPE==PENT_TIME
- VvGetAbsCpuClocks(&(liStartCount.QuadPart));
- #endif
- }
-
- /*************************/
- void CVvDebugTimer::StopAndAccuTime() {
- #if TIMERTYPE==WIN31_TIME
- dwStopCount = GetTickCount();
- qwDeltaCount = (__int64) dwStopCount - (__int64) dwStartCount;
- #else
- #if TIMERTYPE==WIN95_TIME
- QueryPerformanceCounter(&liStopCount);
- #elif TIMERTYPE==PENT_TIME
- VvGetAbsCpuClocks(&(liStopCount.QuadPart));
- #endif
- qwDeltaCount = ((__int64)liStopCount.QuadPart
- -(__int64)liStartCount.QuadPart);
- #if TIMERTYPE==PENT_TIME
- /* magig number, assume that function calls etc. cost 160 cycles */
- qwDeltaCount -= 160;
- #endif
- #endif
- qwDeltaHistory[nDeltaHistoryPtr] = qwDeltaCount;
- nDeltaHistoryPtr++;
- if(nDeltaHistoryPtr >= NBDELTASHISTORY)
- nDeltaHistoryPtr = 0;
- qwAccuCount += qwDeltaCount;
- }
-
- /*************************/
- void CVvDebugTimer::OutputDeltaTime(char *pcLabel, S32 nMaxSkip) {
- char string[80]; /* Flawfinder: ignore */
- nSkipToNextOutput++;//only every nMaxSkip time
- if(nSkipToNextOutput >= nMaxSkip) {
- nSkipToNextOutput = 0;
- #if TIMERTYPE==WIN31_TIME
- SafeSprintf(string, 80,"W31%s: %7.2lf msn", pcLabel, (double) qwDeltaCount);
- #else
- if(nFrequencyValid!=FREQUENCY_VALID) {
- SafeSprintf(string, 80,"%s: %7.2lf msn", pcLabel,
- 1000.*(double)qwDeltaCount/(double) liFrequency.QuadPart);
- } else {
- SafeSprintf(string, 80,"%s: Frequency not validn", pcLabel);
- }
- #endif
- OutputDebugString(string);
- }
- }
- /*************************/
- int CVvDebugTimer::GetAccuTime(double *ptime) {
- int result;
- #if TIMERTYPE==WIN31_TIME
- *time = (double)qwAccuCount;
- result = 1
- #else
- if(nFrequencyValid == FREQUENCY_VALID) {
- *ptime = 1000.*(double)qwAccuCount/((double) liFrequency.QuadPart);
- result = 2;
- } else {
- *ptime = 0;
- result = 0;
- }
- #endif
- return(result);
- }
-
-
- /*************************/
- void CVvDebugTimer::OutputAccuTime(char *pcLabel, S32 nMaxSkip) {
- // we run through it only every nMaxSkip times
- char string[80]; /* Flawfinder: ignore */
- nSkipToNextOutput++;//only every nMaxSkip time
- if(nSkipToNextOutput >= nMaxSkip) {
- nSkipToNextOutput = 0;
- double time;
- int result;
- result = GetAccuTime(&time);
- if(result==1) {
- SafeSprintf(string, 80, "W31%s: %7.2lf msn", pcLabel, time);
- } else if(result==2) {
- SafeSprintf(string, 80, "%s: %7.2lf msn", pcLabel, time);
- } else {
- SafeSprintf(string, 80,"%s: QueryPerformanceFrequency not supportedn", pcLabel);
- }
- OutputDebugString(string);
- }
- }
- /*************************/
- void CVvDebugTimer::LogAccuTime(char *pcLabel, S32 nMaxSkip) {
- // we run through it only every nMaxSkip times
- char string[80]; /* Flawfinder: ignore */
- nSkipToNextOutput++;//only every nMaxSkip time
- if(nSkipToNextOutput >= nMaxSkip) {
- nSkipToNextOutput = 0;
- #if TIMERTYPE==WIN31_TIME
- SafeSprintf(string, 80, "W31%s: %7.2lf msn", pcLabel,
- (double)qwAccuCount);
- #else
- if(nFrequencyValid == FREQUENCY_VALID) {
- SafeSprintf(string, 80,"%s: %7.2lf msn", pcLabel,
- 1000.*(double)qwAccuCount/((double) liFrequency.QuadPart));
- } else {
- SafeSprintf(string, 80,"%s: QueryPerformanceFrequency not supportedn", pcLabel);
- }
- #endif
- dprintf(string);
- }
- }
- #define VVDEBUGOUT(pcOut, string, nbMaxChar)
- if(pcOut) { (strncpy(pcOut, string, nbMaxChar)); } else {(OutputDebugString(string));} /* Flawfinder: ignore */
- /*************************/
- void CVvDebugTimer::AverageAndOutputAccuTime(char *pcLabel, S32 nMaxSkip,
- char *pcOut=0, S32 nbMaxChar=0) {
- // we run through it only every nMaxSkip times
- char string[800]; /* Flawfinder: ignore */
- qwAverageAccuCount += qwAccuCount;
- nSkipToNextOutput++;//only every nMaxSkip time
- if(nSkipToNextOutput >= nMaxSkip) {
- #if TIMERTYPE==WIN31_TIME
- SafeSprintf(string, 800, "W31%s: %7.2lf msn", pcLabel,
- (double)qwAverageAccuCount/(double) nSkipToNextOutput);
- #else
- if(nFrequencyValid == FREQUENCY_VALID) {
- S32 ii;
- char appendix[20]; /* Flawfinder: ignore */
- sprintf(string, "("); /* Flawfinder: ignore */
- for(ii=0; ii<nDeltaHistoryPtr; ii++) {
- SafeSprintf(appendix, 20,"%3.1lf ",
- 1000.*(double)qwDeltaHistory[ii]/
- ((double) liFrequency.QuadPart));
- SafeStrCat(string, appendix, 800);
- }
- SafeStrCat(string, ")n", 800);
- VVDEBUGOUT(pcOut, string, nbMaxChar);
- SafeSprintf(string, 800,"%s: %7.2lf msn", pcLabel,
- 1000.*(double)qwAverageAccuCount
- /((double) liFrequency.LowPart + 4294967296.*liFrequency.HighPart)
- /(double) nSkipToNextOutput);
- VVDEBUGOUT(pcOut, string, nbMaxChar);
- } else {
- SafeSprintf(string, 800,"%s: QueryPerformanceFrequency not supportedn", pcLabel);
- VVDEBUGOUT(pcOut, string, nbMaxChar);
- }
- #endif
- qwAverageAccuCount = 0;
- nSkipToNextOutput = 0;
- nDeltaHistoryPtr = 0;
- }
- }
- /********************************/
- /* this is for c interface */
- extern "C" {
- // external member functions
- void ResetTime(CVvDebugTimer *p) {
- p->qwAccuCount = 0;
- p->qwDeltaCount = 0;
-
- }
- // ctors, dtors, etc.
- CVvDebugTimer * newCVvDebugTimer () {
- CVvDebugTimer *Tim;
- Tim = new CVvDebugTimer;
- Tim->ResetTime();
- Tim->qwAverageAccuCount = 0;
- Tim->nSkipToNextOutput = 0;
- if(nFrequencyValid==FREQUENCY_NOTMEASURED) {
- MeasureFrequency();
- }
- return Tim;
- }
- void AverageAndOutputAccuTime(CVvDebugTimer *p, char *pcLabel, S32 nMaxSkip) {
- if(p)
- p->AverageAndOutputAccuTime(pcLabel, nMaxSkip, 0, 0);
- }
- void AverageAndOutputAccuTimeString(CVvDebugTimer *p, char *pcLabel, S32 nMaxSkip,
- char *pcOut=0, S32 nbMaxChar=0) {
- if(p)
- p->AverageAndOutputAccuTime(pcLabel, nMaxSkip, pcOut, nbMaxChar);
- }
- int GetAccuTime(CVvDebugTimer *p, double *ptime) {
- int result=0;
- *ptime = 0.;
- if(p)
- result = p->GetAccuTime(ptime);
- return(result);
- }
- void OutputAccuTime(CVvDebugTimer *p, char *pcLabel, S32 nMaxSkip) {
- if(p)
- p->OutputAccuTime(pcLabel, nMaxSkip);
- }
- void LogAccuTime(CVvDebugTimer *p, char *pcLabel, S32 nMaxSkip) {
- if(p)
- p->LogAccuTime(pcLabel, nMaxSkip);
- }
- void OutputDeltaTime(CVvDebugTimer *p, char *pcLabel, S32 nMaxSkip) {
- if(p)
- p->OutputDeltaTime(pcLabel, nMaxSkip);
- }
-
- void StopAndAccuTime(CVvDebugTimer *p) {
- if(p)
- p->StopAndAccuTime();
- }
- void StartTime(CVvDebugTimer *p) {
- if(p)
- p->StartTime();
- }
- }