C++ 如何使用 QueryPerformanceCounter?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1739259/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to use QueryPerformanceCounter?
提问by Anonymous
I recently decided that I needed to change from using milliseconds to microseconds for my Timer class, and after some research I've decided that QueryPerformanceCounter is probably my safest bet. (The warning on Boost::Posix
that it may not works on Win32 API put me off a bit). However, I'm not really sure how to implement it.
我最近决定我的 Timer 类需要从使用毫秒更改为微秒,经过一些研究,我决定 QueryPerformanceCounter 可能是我最安全的选择。(关于Boost::Posix
它可能不适用于 Win32 API的警告让我有点失望)。但是,我不确定如何实现它。
What I'm doing is calling whatever GetTicks()
esque function I'm using and assigning it to Timer's startingTicks
variable. Then to find the amount of time passed I just subtract the function's return value from the startingTicks
, and when I reset the timer I just call the function again and assign startingTicks to it. Unfortunately, from the code I've seen it isn't as simple as just calling QueryPerformanceCounter()
, and I'm not sure what I'm supposed to pass as its argument.
我正在做的是调用GetTicks()
我正在使用的任何esque 函数并将其分配给 Timer 的startingTicks
变量。然后为了找到经过的时间量,我只需从 中减去函数的返回值startingTicks
,当我重置计时器时,我只需再次调用该函数并为其分配startingTicks。不幸的是,从我看到的代码来看,它并不像调用 那样简单QueryPerformanceCounter()
,而且我不确定我应该传递什么作为它的参数。
回答by Ramónster
#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;
}
This program should output a number close to 1000 (windows sleep isn't that accurate, but it should be like 999).
这个程序应该输出一个接近 1000 的数字(windows sleep 不是那么准确,但它应该像 999)。
The StartCounter()
function records the number of ticks the performance counter has in the CounterStart
variable. The GetCounter()
function returns the number of milliseconds since StartCounter()
was last called as a double, so if GetCounter()
returns 0.001 then it has been about 1 microsecond since StartCounter()
was called.
该StartCounter()
函数记录性能计数器在CounterStart
变量中的滴答数。该GetCounter()
函数StartCounter()
以双精度形式返回自上次调用以来的毫秒数,因此如果GetCounter()
返回 0.001,则自StartCounter()
调用以来已经过去了大约 1 微秒。
If you want to have the timer use seconds instead then change
如果您想让计时器使用秒,然后更改
PCFreq = double(li.QuadPart)/1000.0;
to
到
PCFreq = double(li.QuadPart);
or if you want microseconds then use
或者如果你想要微秒然后使用
PCFreq = double(li.QuadPart)/1000000.0;
But really it's about convenience since it returns a double.
但实际上这是为了方便,因为它返回一个双精度值。
回答by Anonymous
I use these defines:
我使用这些定义:
/** 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;
Usage (brackets to prevent redefines):
用法(防止重新定义的括号):
TIMER_INIT
{
TIMER_START
Sleep(1000);
TIMER_STOP
}
{
TIMER_START
Sleep(1234);
TIMER_STOP
}
Output from usage example:
使用示例的输出:
1.00003 sec
1.23407 sec
回答by Alex Martelli
Assuming you're on Windows (if so you should tag your question as such!), on this MSDN pageyou can find the source for a simple, useful HRTimer
C++ class that wraps the needed system calls to do something very close to what you require (it would be easy to add a GetTicks()
method to it, in particular, to do exactlywhat you require).
假设你在 Windows 上(如果是这样,你应该标记你的问题!),在这个 MSDN 页面上,你可以找到一个简单、有用的HRTimer
C++ 类的源代码,它包装了所需的系统调用来做一些非常接近你需要的事情(很容易向其中添加GetTicks()
方法,特别是完全按照您的要求进行操作)。
On non-Windows platforms, there's no QueryPerformanceCounter function, so the solution won't be directly portable. However, if you do wrap it in a class such as the above-mentioned HRTimer
, it will be easier to change the class's implementation to use what the current platform is indeed able to offer (maybe via Boost or whatever!).
在非 Windows 平台上,没有 QueryPerformanceCounter 函数,因此该解决方案不能直接移植。但是,如果您确实将它包装在一个类中,例如上述HRTimer
,则更容易更改类的实现以使用当前平台确实能够提供的内容(可能通过 Boost 或其他方式!)。
回答by kagali-san
I would extend this question with a NDIS driver example on getting time. As one knows, KeQuerySystemTime (mimicked under NdisGetCurrentSystemTime) has a low resolution above milliseconds, and there are some processes like network packets or other IRPs which may need a better timestamp;
我会用 NDIS 驱动程序示例来扩展这个问题以获取时间。众所周知,KeQuerySystemTime(模仿NdisGetCurrentSystemTime)在毫秒级以上的分辨率很低,并且有一些进程如网络数据包或其他IRP可能需要更好的时间戳;
The example is just as simple:
这个例子也很简单:
LONG_INTEGER data, frequency;
LONGLONG diff;
data = KeQueryPerformanceCounter((LARGE_INTEGER *)&frequency)
diff = data.QuadPart / (Frequency.QuadPart/$divisor)
where divisor is 10^3, or 10^6 depending on required resolution.
其中除数是 10^3 或 10^6,具体取决于所需的分辨率。