什么是timeGetTime最好的替代品,以避免环绕?

timeGetTime似乎是相当不错的查询系统时间。 但是,它的返回值只有32位,所以它大约每49天左右一次。

在调用代码中检测翻转并不难,但是增加了一些复杂性,并且(更糟糕)需要保持一个状态。

是否有替代timeGetTime不会有这个环绕问题(可能通过返回一个64位值),并具有大致相同的精度和成本?

Solutions Collecting From Web of "什么是timeGetTime最好的替代品,以避免环绕?"

不,跟踪翻转需要状态。 它可以像在每个回调中增加自己的64位计数器一样简单。

想要追踪分辨率低至1毫秒的分辨率长达49天是非常不寻常的。 在这么长的一段时间之后,你不得不担心精度仍然存在。 下一步是使用时钟,GetTickCount(64),GetSystemTimeAsFileTime具有15.625毫秒的分辨率,并通过时间服务器保持精确。

什么平台?

如果你在Vista或更高版本上运行,你可以使用GetTickCount64() ,或者从GetTickCount()和一个定时器合成你自己的GetTickCount64()

我处理GetTickCount()的滚动问题,并在我的博客上关于测试非平凡代码的平台上综合了一个GetTickCount64() ,这些平台不支持它: http : //www.lenholgate.com/blog/2008/04 /practical-testing-17—a-whole-new-approach.html

除非您需要计算超过49天的事件,否则您可以安全地忽略这个回绕 。 只要总是从当前timeGetTime()中减去前一个timeGetTime(),即使在整个换行过程中,您也将始终获得准确的增量测量时间, 前提是您的总时长不足49天 。 这一切都是由于计算机内部的无符号数学运算。

 // this code ALWAYS works, even with wrap-around! DWORD dwStart = timeGetTime(); // provided the event timed here has a duration of less than 49 days DWORD dwDuration = timeGetTime()-dwStart; 

提示:查看TimeBeginPeriod(1L)以提高timeGetTime()的准确性。

但是…如果你想要一个64位版本的timeGetTime,这里是:

 __int64 timeGetTime64() { static __int64 time64=0; // warning: if multiple threads call this function, protect with a critical section! return (time64 += (timeGetTime()-(DWORD)time64)); } 

请注意,如果至少每49天调用一次该函数,则此函数将无法正确检测到绕回。

看看GetSystemTimeAsFileTime() 。 它填充了一个FILETIME结构,它包含一个“自1601年1月1日(UTC)以来代表100纳秒间隔数的64位值”

你如何使用它? 我经常使用Win32等价物来检查我知道的持续时间是否在49天以下。 例如下面的代码将始终工作。

 DWORD start = timeGetTime(); DoSomthingThatTakesLessThen49Days(); DWORD duration = timeGetTime() - start; 

即使调用DoSomthingThatTakesLessThen49Days duration timeGetTime仍然是正确的。

请注意以下代码可能会在滚动时失败。

 DWORD start = timeGetTime(); DoSomthingThatTakesLessThen49Days(); if (now + 5000 < timeGetTime()) { } 

但可以轻松地重新编写工作如下

 DWORD start = timeGetTime(); DoSomthingThatTakesLessThen49Days(); if (timeGetTime() - start < 5000) { } 

假设你可以保证这个函数每49天至少会调用一次,像这样的东西可以工作:

 // Returns current time in milliseconds uint64_t timeGetTime64() { static uint32_t _prevVal = 0; static uint64_t _wrapOffset = 0; uint32_t newVal = (uint32_t) timeGetTime(); if (newVal < _prevVal) _wrapOffset += (((uint64_t)1)<<32); _prevVal = newVal; return _wrapOffset+newVal; } 

请注意,由于使用静态变量,此函数不是多线程安全的,所以如果您打算从多个线程调用它,则应通过临界区或互斥体或类似的方法将其序列化。

你可以使用RDTSC固有的。 要获得毫秒的时间,你可以得到变换系数:

 double get_rdtsc_coeff() { static double coeff = 0.0; if ( coeff < 1.0 ) { // count it only once unsigned __int64 t00 = __rdtsc(); Sleep(1000); unsigned __int64 t01 = __rdtsc(); coeff = (t01-t00)/1000.0; } return coeff; // transformation coefficient } 

现在您可以从上次重置开始计算毫秒数:

 __int64 get_ms_from_start() { return static_cast<__int64>(__rdtsc()/get_rdtsc_coeff()); } 

如果您的系统使用SpeedStep或类似的技术,您可以使用QueryPerformanceCounter / QueryPerformanceFrequency函数。 Windows保证在系统运行时频率不能改变。

我不确定这是否完全满足您的需求,但是

 std::chrono::system_clock 

可能是你正在寻找的东西。

http://en.cppreference.com/w/cpp/chrono/system_clock