windows 下最可靠的高精度计时方式是 queryperformancecounter,需配合 queryperformancefrequency 换算为秒,不可直接将 quadpart 当作时间单位;linux/macos 应用 clock_gettime(clock_monotonic) 替代,避免使用 clock_realtime 或 gettimeofday。

Windows 上用 QueryPerformanceCounter 获取高精度 Tick
Windows 下最可靠、最常用的高精度计时方式就是 QueryPerformanceCounter,它返回的是硬件计数器的原始 tick 值(通常来自 TSC 或专用计数器),分辨率可达纳秒级。但要注意:它返回的不是时间戳,而是相对计数值,必须配合 QueryPerformanceFrequency 换算成秒。
常见错误是直接把 LARGE_INTEGER 的 QuadPart 当作微秒或毫秒用——它只是 raw count,没单位。另一个坑是未检查 QueryPerformanceCounter 返回值:在极老或虚拟化严重环境中可能失败(返回 0),应做判断。
示例用法:
LARGE_INTEGER freq, start, end;
if (!QueryPerformanceFrequency(&freq) || freq.QuadPart == 0) {
// 不支持高精度计时
}
QueryPerformanceCounter(&start);
// ... 业务代码 ...
QueryPerformanceCounter(&end);
double elapsed_sec = (double)(end.QuadPart - start.QuadPart) / freq.QuadPart;
Linux/macOS 用 clock_gettime(CLOCK_MONOTONIC) 替代
POSIX 系统没有 QueryPerformanceCounter,clock_gettime(CLOCK_MONOTONIC) 是标准且推荐的替代方案。它返回的是自某个未指定起点以来的单调递增时间(纳秒级),不受系统时间调整影响,适合测量耗时。
别用 CLOCK_REALTIME 测性能——它会被 NTP 调整、闰秒插入干扰;也别依赖 gettimeofday,它的分辨率通常只有微秒,且在某些内核配置下可能回退。
关键点:
-
struct timespec的tv_nsec是 0–999999999,不是百分之一秒 - 计算差值时注意
tv_nsec借位:如果 end.tv_nsec tv_sec 借 1 秒 - 部分旧系统(如 CentOS 6 内核)对
CLOCK_MONOTONIC支持不完整,可 fallback 到CLOCK_MONOTONIC_RAW(若可用)
C++11 std::chrono::high_resolution_clock 的实际行为
很多人以为 std::chrono::high_resolution_clock 就是“最高精度时钟”,但它在不同标准库实现中底层可能映射到完全不同东西:libstdc++(GCC)通常用 clock_gettime(CLOCK_MONOTONIC),而 libc++(Clang/macOS)有时会 fallback 到 CLOCK_UPTIME_RAW 或甚至 mach_absolute_time。Windows 上 MSVC 的实现则基于 QueryPerformanceCounter。
这意味着跨平台代码里直接依赖 high_resolution_clock::is_steady 或假设其分辨率一致,很容易出问题。更稳妥的做法是:只用它做相对计时(如 duration_cast 差值),不把它当绝对时间源;需要纳秒级精度时,仍建议手写平台专用逻辑。
一个典型陷阱:
auto t1 = std::chrono::high_resolution_clock::now(); std::this_thread::sleep_for(std::chrono::milliseconds(1)); auto t2 = std::chrono::high_resolution_clock::now(); // 这里 t2 - t1 可能远小于 1ms(调度延迟)或略大于(精度限制),但不能反推系统 tick 频率
跨平台封装时绕不开的两个细节
真正写跨平台高精度 tick 封装时,有两个点容易被忽略:
-
QueryPerformanceFrequency在 Windows 上可能返回非整数值(比如某些 AMD CPU 的 TSC 频率不稳定),所以除法必须用double,不能用整数除 - Linux 下
clock_gettime的实际分辨率取决于硬件和内核配置,/proc/sys/kernel/timer_freq或CONFIG_HIGH_RES_TIMERS=y才保证纳秒级,否则可能回落到 10ms 量级——这无法在运行时检测,只能文档注明约束
如果你要导出一个统一的 uint64_t get_tick_count() 接口,Windows 返回 QueryPerformanceCounter 的 raw value,Linux/macOS 就得自己乘以频率再取整,否则语义不一致。这种“统一 raw tick”模型看似方便,实则掩盖了底层差异,调试时容易误判。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











