为何Qt currentMSecsSinceEpoch晚调用却有时比chrono时间戳小?
Qt的currentMSecsSinceEpoch和std::chrono::system_clock::now()返回的时间戳存在差异,哪怕先调用STL的时间函数再调用Qt的,Qt返回的时间戳有时仍会更小,具体原因可从以下几点分析:
测试代码
#include <iostream> #include <chrono> #include <QtCore> int main() { namespace sc = std::chrono; for (int j = 0; j < 10; ++j) { const auto stl_now = sc::system_clock::now(); std::this_thread::sleep_for(sc::microseconds{1}); const auto qt_now = QDateTime::currentMSecsSinceEpoch(); const auto duration_since_epoch = stl_now.time_since_epoch(); std::cout << '\n'; std::cout << "1. Chrono now: " << duration_since_epoch.count() << '\n'; std::cout << "1. Chrono now (floored): " << sc::floor<sc::milliseconds>(duration_since_epoch).count() << '\n'; std::cout << "2. Qt now: " << qt_now << '\n'; } }
测试输出
1. Chrono now: 17012623315247298 1. Chrono now (floored): 1701262331524 2. Qt now: 1701262331524 1. Chrono now: 17012623315265318 1. Chrono now (floored): 1701262331526 2. Qt now: 1701262331526 1. Chrono now: 17012623315279808 1. Chrono now (floored): 1701262331527 2. Qt now: 1701262331527 1. Chrono now: 17012623315296035 1. Chrono now (floored): 1701262331529 2. Qt now: 1701262331529 1. Chrono now: 17012623315314812 1. Chrono now (floored): 1701262331531 2. Qt now: 1701262331531 1. Chrono now: 17012623315332218 1. Chrono now (floored): 1701262331533 2. Qt now: 1701262331532 1. Chrono now: 17012623315347844 1. Chrono now (floored): 1701262331534 2. Qt now: 1701262331534 1. Chrono now: 17012623315362278 1. Chrono now (floored): 1701262331536 2. Qt now: 1701262331535 1. Chrono now: 17012623315378605 1. Chrono now (floored): 1701262331537 2. Qt now: 1701262331537 1. Chrono now: 17012623315393145 1. Chrono now (floored): 1701262331539 2. Qt now: 1701262331539
差异原因
底层API的精度与处理方式不同
std::chrono::system_clock::now()一般调用系统高精度时间接口(比如Windows的GetSystemTimePreciseAsFileTime、Linux的clock_gettime(CLOCK_REALTIME)),精度可达微秒甚至纳秒级。而Qt的currentMSecsSinceEpoch()可能依赖精度较低的系统API,或是对高精度时间做了直接截断而非向下取整。比如当系统时间处于1533.2218毫秒时,chrono向下取整得到1533,但如果Qt的实现刚好读取的是未更新的毫秒整数值,就会出现比chrono取整后小1的情况。时钟更新与缓存机制差异
系统时钟的更新不是完全连续的,不同API可能使用不同的时钟源或缓存策略。Qt的时间函数可能读取了缓存的毫秒值,而chrono读取的是实时高精度值,当缓存值还未同步到最新毫秒时,就会出现Qt时间戳更小的情况。线程调度的不可控延迟
代码中虽然加了1微秒的sleep,但线程调度延迟无法精确控制。有可能调用chrono后线程被挂起,恢复执行调用Qt函数时,系统的毫秒时钟还没跳转到下一个区间,而chrono记录的时间已经进入下一个毫秒,导致Qt返回上一个毫秒的值,从而比chrono取整结果小。
内容的提问来源于stack exchange,提问作者Snincent

