繁体   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