精確的時間計時,有時候是非常必要的。比如播放多媒體時視頻與音頻的時間同步,還有在測試代碼的性能時,也需要使用到非常精確的時間計時。還有測試硬件的性能時,也需要精確的時間計時。這時就需要使用QueryPerformanceCounter來查詢定時器的計數值,如果硬件裏有定時器,它就會啓動這個定時器,並且不斷獲取定時器的值,這樣的定時器精度,就跟硬件時鐘的晶振一樣精確的。
QueryPerformanceCounter 查詢性能計數器
The QueryPerformanceCounter function retrieves the current value of the high-resolution performance counter, if one exists.
此函數用於獲取精確的性能計數器數值,如果存在.
BOOL QueryPerformanceCounter(
LARGE_INTEGER *lpPerformanceCount // address of current counter value 當前計數器值的地址
);
Parameters
lpPerformanceCount
Points to a variable that the function sets, in counts, to the current performance-counter value. If the installed hardware does not support a high-resolution performance counter, this parameter can be to zero.
指針,指向函數設置的一個變量(一般是個引用,譯者注), 用來返回性能計數器的值.如果已安裝的硬件不支持高精度性能計數器,此參數可以爲0(那調用有什麼意義,用來查詢?).
Return Values
If the installed hardware supports a high-resolution performance counter, the return value is nonzero.
不支持,返回非0
If the installed hardware does not support a high-resolution performance counter, the return value is zero.
否則返回0
下面有個例子:
WINBASEAPI
BOOL
WINAPI
QueryPerformanceCounter(
__out LARGE_INTEGER *lpPerformanceCount
);
WINBASEAPI
BOOL
WINAPI
QueryPerformanceFrequency(
__out LARGE_INTEGER *lpFrequency
);
lpPerformanceCount是返回定時器當前計數值。
QueryPerformanceFrequency是返回定時器的頻率。
調用函數的例子如下:
//精確時鐘查詢。
void TestHighTimer(void)
{
//
LARGE_INTEGER nFreq;
LARGE_INTEGER nLastTime1;
LARGE_INTEGER nLastTime2;
//獲取是否支持精確定時器。
if (QueryPerformanceFrequency(&nFreq))
{
//
const int nBufSize = 256;
TCHAR chBuf[nBufSize];
//顯示定時器的頻率。
wsprintf(chBuf,_T("LastTime=%I64d/r/n"),nFreq);
OutputDebugString(chBuf);
//獲取定時器的值。
QueryPerformanceCounter(&nLastTime1);
wsprintf(chBuf,_T("LastTime=%I64d/r/n"),nLastTime1);
OutputDebugString(chBuf);
Sleep(0);
//獲取定時器的值。
QueryPerformanceCounter(&nLastTime2);
wsprintf(chBuf,_T("LastTime=%I64d/r/n"),nLastTime2);
OutputDebugString(chBuf);
//計算時間是花費多少秒。
float fInterval = nLastTime2.QuadPart - nLastTime1.QuadPart;
swprintf(chBuf,nBufSize,_T("花費:%f/r/n"),fInterval/(float)nFreq.QuadPart);
OutputDebugString(chBuf);
}
}
以上文章原文地址:http://blog.csdn.net/daoyuly/article/details/3947918
/************************************************************************************************************************************************************************************/
LARGE_INTEGER tima,timb;
QueryPerformanceCounter(&tima);
在 Windows Server 2003 和 WindowsXP 中使用 QueryPerformanceCounter 函數的程序可能執行不當
QueryPerformanceCounter 來精確計算執行時間
QueryPerformanceCounter 來精確計算執行時間
// 這個程式展示瞭如何使用QueryPerformanceCounter 來精確計算執行時間
//代碼
- LARGE_INTEGER m_liPerfFreq={0};
- //獲取每秒多少CPU Performance Tick
- QueryPerformanceFrequency(&m_liPerfFreq);
- LARGE_INTEGER m_liPerfStart={0};
- QueryPerformanceCounter(&m_liPerfStart);
- for(int i=0; i< 100; i++)
- cout << i << endl;
- LARGE_INTEGER liPerfNow={0};
- // 計算CPU運行到現在的時間
- QueryPerformanceCounter(&liPerfNow);
- int time=( ((liPerfNow.QuadPart - m_liPerfStart.QuadPart) * 1000)/m_liPerfFreq.QuadPart);
- char buffer[100];
- sprintf(buffer,"執行時間 %d millisecond ",time);
- cout<<buffer<<endl;
QueryPerformanceCounter()這個函數返回高精確度性能計數器的值,它可以以微妙爲單位計時.但是QueryPerformanceCounter()確切的精確計時的最小單位是與系統有關的,所以,必須要查詢系統以得到QueryPerformanceCounter()返回的嘀噠聲的頻率.
QueryPerformanceFrequency()提供了這個頻率值,返回每秒嘀噠聲的個數.
計算確切的時間是從第一次調用QueryPerformanceCounter()開始的
假設得到的LARGE_INTEGER爲nStartCounter,過一段時間後再次調用該函數結束的,
設得到nStopCounter.
兩者之差除以QueryPerformanceFrequency()的頻率就是開始到結束之間的秒數.由於計時函數本身要耗費很少的時間,要減去一個很少的時間開銷.但一般都把這個開銷忽略.公式如下:
nStopCounter-nStartCounter
ElapsedTime=------------------------------------ - overhead
frequency
double time=(nStopCounter.QuadPart-nStartCounter.QuadPart)/frequency.QuadPart
這兩個函數是VC提供的僅供Windows 95及其後續版本使用的精確時間函數,並要求計算機從硬件上支持精確定時器。
QueryPerformanceFrequency()函數和QueryPerformanceCounter()函數的原型如下:
BOOL QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency); BOOL QueryPerformanceCounter(LARGE_INTEGER *lpCount);
數據類型ARGE_INTEGER既可以是一個8字節長的整型數,也可以是兩個4字節長的整型數的聯合結構, 其具體用法根據編譯器是否支持64位而定。該類型的定義如下:
typedef union _LARGE_INTEGER { struct { DWORD LowPart ;// 4字節整型數 LONG HighPart;// 4字節整型數 }; LONGLONG QuadPart ;// 8字節整型數 }LARGE_INTEGER ;
在進行定時之前,先調用QueryPerformanceFrequency()函數獲得機器內部定時器的時鐘頻率, 然後在需要嚴格定時的事件發生之前和發生之後分別調用QueryPerformanceCounter()函數,利用兩次獲得的計數之差及時鐘頻率,計算出事件經 歷的精確時間。下列代碼實現1ms的精確定時:
- LARGE_INTEGER litmp;
- LONGLONG QPart1,QPart2;
- double dfMinus, dfFreq, dfTim;
- QueryPerformanceFrequency(&litmp);
- dfFreq = (double)litmp.QuadPart;// 獲得計數器的時鐘頻率
- QueryPerformanceCounter(&litmp);
- QPart1 = litmp.QuadPart;// 獲得初始值
- do
- {
- QueryPerformanceCounter(&litmp);
- QPart2 = litmp.QuadPart;//獲得中止值
- dfMinus = (double)(QPart2-QPart1);
- dfTim = dfMinus / dfFreq;// 獲得對應的時間值,單位爲秒
- }while(dfTim<0.001);
其定時誤差不超過1微秒,精度與CPU等機器配置有關。 下面的程序用來測試函數Sleep(100)的精確持續時間:
- LARGE_INTEGER litmp;
- LONGLONG QPart1,QPart2;
- double dfMinus, dfFreq, dfTim;
- QueryPerformanceFrequency(&litmp);
- dfFreq = (double)litmp.QuadPart;// 獲得計數器的時鐘頻率
- QueryPerformanceCounter(&litmp);
- QPart1 = litmp.QuadPart;// 獲得初始值
- Sleep(100);
- QueryPerformanceCounter(&litmp);
- QPart2 = litmp.QuadPart;//獲得中止值
- dfMinus = (double)(QPart2-QPart1);
- dfTim = dfMinus / dfFreq;// 獲得對應的時間值,單位爲秒
由於Sleep()函數自身的誤差,上述程序每次執行的結果都會有微小誤差。下列代碼實現1微秒的精確定時:
- LARGE_INTEGER litmp;
- LONGLONG QPart1,QPart2;
- double dfMinus, dfFreq, dfTim;
- QueryPerformanceFrequency(&litmp);
- dfFreq = (double)litmp.QuadPart;// 獲得計數器的時鐘頻率
- QueryPerformanceCounter(&litmp);
- QPart1 = litmp.QuadPart;// 獲得初始值
- do
- {
- QueryPerformanceCounter(&litmp);
- QPart2 = litmp.QuadPart;//獲得中止值
- dfMinus = (double)(QPart2-QPart1);
- dfTim = dfMinus / dfFreq;// 獲得對應的時間值,單位爲秒
- }while(dfTim<0.000001);
其定時誤差一般不超過0.5微秒,精度與CPU等機器配置有關。
以上文章原文地址:http://blog.csdn.net/lsmdiao0812/article/details/3173374