我最近决定我需要为我的Timer类从使用毫秒更改为微秒,经过一些研究后,我认为QueryPerformanceCounter可能是我最安全的选择。 (Boost::Posix
上警告它可能无法在Win32 API上运行,这让我有所帮助)。但是,我不确定如何实现它。
我正在做的是调用我正在使用的GetTicks()
esque函数并将其分配给Timer的startingTicks
变量。然后为了找到传递的时间量,我只需从startingTicks
中减去函数的返回值,当我重置计时器时,我再次调用该函数并为其分配startingTicks。不幸的是,从我看到的代码中,它并不像调用QueryPerformanceCounter()
那么简单,而且我不确定我应该传递什么作为它的论点。
答案 0 :(得分:152)
#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()
最后一次调用为double以来的毫秒数,因此如果GetCounter()
返回0.001,那么自调用StartCounter()
起约为1微秒。
如果您想让计时器使用秒而不是更改
PCFreq = double(li.QuadPart)/1000.0;
到
PCFreq = double(li.QuadPart);
或者如果你想要微秒,那么使用
PCFreq = double(li.QuadPart)/1000000.0;
但真的是方便,因为它会返回一个双倍。
答案 1 :(得分:17)
我使用这些定义:
/** 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
答案 2 :(得分:2)
假设您在Windows上(如果是这样,您应该标记您的问题!),在this MSDN page上,您可以找到包含所需系统的简单,有用的HRTimer
C ++类的源代码要求做一些非常接近你需要的事情(向它添加GetTicks()
方法很容易,特别是完全你需要的东西。)
在非Windows平台上,没有QueryPerformanceCounter功能,因此解决方案不能直接移植。但是,如果你把它包装在像上面提到的HRTimer
这样的类中,那么更改类的实现以使用当前平台确实能够提供的内容(可能通过Boost或其他任何东西)会更容易!
答案 3 :(得分:1)
我会用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,具体取决于所需的分辨率。