簡體   English   中英

如何使用QueryPerformanceCounter?

[英]How to use QueryPerformanceCounter?

我最近決定我需要為我的Timer類從使用毫秒更改為微秒,經過一些研究后,我認為QueryPerformanceCounter可能是我最安全的選擇。 Boost::Posix上的警告,它可能無法在Win32 API上運行,這讓我有點失望)。 但是,我不確定如何實現它。

我正在做的是調用我正在使用的任何GetTicks() esque函數並將其分配給Timer的startingTicks變量。 然后為了找到傳遞的時間量,我只需從startingTicks減去函數的返回值,當我重置計時器時,我再次調用該函數並為其分配startingTicks。 不幸的是,從我看到的代碼來看,它並不像調用QueryPerformanceCounter()那么簡單,而且我不確定我應該傳遞什么作為它的參數。

#include <windows.h>

double PCFreq = 0.0;
__int64 CounterStart = 0;

void StartCounter()
{
    LARGE_INTEGER li;
    if(!QueryPerformanceFrequency(&li))
    cout << "QueryPerformanceFrequency failed!\n";

    PCFreq = double(li.QuadPart)/1000.0;

    QueryPerformanceCounter(&li);
    CounterStart = li.QuadPart;
}
double GetCounter()
{
    LARGE_INTEGER li;
    QueryPerformanceCounter(&li);
    return double(li.QuadPart-CounterStart)/PCFreq;
}

int main()
{
    StartCounter();
    Sleep(1000);
    cout << GetCounter() <<"\n";
    return 0;
}

這個程序應該輸出接近1000的數字(窗口睡眠不准確,但它應該像999)。

StartCounter()函數記錄性能計數器在CounterStart變量中的滴答數。 GetCounter()函數返回自上次調用StartCounter()的毫秒數,因此如果GetCounter()返回0.001,那么自調用StartCounter()以來它已經大約1微秒。

如果你想讓計時器使用秒而不是更改

PCFreq = double(li.QuadPart)/1000.0;

PCFreq = double(li.QuadPart);

或者如果你想要微秒然后使用

PCFreq = double(li.QuadPart)/1000000.0;

但實際上它是關於方便,因為它返回一個雙倍。

我使用這些定義:

/** Use to init the clock */
#define TIMER_INIT \
    LARGE_INTEGER frequency; \
    LARGE_INTEGER t1,t2; \
    double elapsedTime; \
    QueryPerformanceFrequency(&frequency);


/** Use to start the performance timer */
#define TIMER_START QueryPerformanceCounter(&t1);

/** Use to stop the performance timer and output the result to the standard stream. Less verbose than \c TIMER_STOP_VERBOSE */
#define TIMER_STOP \
    QueryPerformanceCounter(&t2); \
    elapsedTime=(float)(t2.QuadPart-t1.QuadPart)/frequency.QuadPart; \
    std::wcout<<elapsedTime<<L" sec"<<endl;

用法(括號以防止重新定義):

TIMER_INIT

{
   TIMER_START
   Sleep(1000);
   TIMER_STOP
}

{
   TIMER_START
   Sleep(1234);
   TIMER_STOP
}

使用示例的輸出:

1.00003 sec
1.23407 sec

假設您在Windows上(如果是這樣,您應該標記您的問題!),在這個MSDN頁面上,您可以找到一個簡單,有用的HRTimer C ++類的源代碼,該類包裝所需的系統調用以執行與您非常接近的操作require(向它添加一個GetTicks()方法很容易,特別是要完全按照你的要求)。

在非Windows平台上,沒有QueryPerformanceCounter函數,因此該解決方案不能直接移植。 但是,如果你將它包裝在一個類(如上面提到的HRTimer ,那么更改類的實現以使用當前平台確實能夠提供的內容(可能通過Boost或其他任何東西!)會更容易。

我會用NDIS驅動程序示例擴展這個問題以獲取時間。 眾所周知,KeQuerySystemTime(在NdisGetCurrentSystemTime下模仿)具有高於毫秒的低分辨率,並且有一些過程如網絡數據包或其他IRP可能需要更好的時間戳;

這個例子很簡單:

LONG_INTEGER data, frequency;
LONGLONG diff;
data = KeQueryPerformanceCounter((LARGE_INTEGER *)&frequency)
diff = data.QuadPart / (Frequency.QuadPart/$divisor)

除數是10 ^ 3,或10 ^ 6,具體取決於所需的分辨率。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM