首选 std::chrono::steady_clock 获取跨平台 wall time,因其不受系统时间调整影响;避免使用 system_clock、high_resolution_clock 或平台特定 API 如 QueryPerformanceCounter 和 clock_gettime。

用 std::chrono::steady_clock 获取 wall time 最可靠
Windows/Linux/macOS 上跨平台获取程序真实经过时间(wall time),首选 std::chrono::steady_clock。它不随系统时间调整跳变,也不受 NTP 校准影响,专为测量间隔而生。
常见错误是误用 std::chrono::system_clock —— 它反映的是挂钟时间,若程序运行中系统时间被手动修改或 NTP 同步,结果会突变甚至倒退。
- 启动时记录:
auto start = std::chrono::steady_clock::now(); - 结束时计算差值:
auto dur = std::chrono::steady_clock::now() - start; - 转成秒(double):
std::chrono::duration<double>(dur).count()</double>
Windows 下用 QueryPerformanceCounter 是备选但要小心
在需要极高精度(亚微秒级)且只跑 Windows 的场景,QueryPerformanceCounter 确实可用,但它依赖硬件计数器,不同 CPU 核心频率可能不一致(尤其在节能模式下),多线程调用需额外同步。
更关键的是:它的返回值是“滴答数”,必须配合 QueryPerformanceFrequency 换算,且该频率在某些旧虚拟机或超频机器上可能不稳定。
立即学习“C++免费学习笔记(深入)”;
- 不要直接用
GetTickCount64:分辨率只有 10–16ms,且 49.7 天后溢出回绕 - 避免在循环中反复调用
QueryPerformanceFrequency:它开销不小,应缓存一次结果 - 若用它,务必检查返回值是否为 0(表示不支持高精度计数器)
Linux/macOS 不要用 clock_gettime(CLOCK_MONOTONIC) 手动封装
std::chrono::steady_clock 在主流 libc++/libstdc++ 实现中底层就是调用 clock_gettime(CLOCK_MONOTONIC),自己封装反而容易出错:比如忘记处理 tv_nsec 进位、忽略 clock_gettime 可能的负误差、或误用 CLOCK_REALTIME。
除非你在写 C 接口库或极度受限的嵌入式环境,否则没必要绕过标准库。C++11 起 steady_clock 已足够健壮。
- 确认编译器支持:GCC 4.8+、Clang 3.3+、MSVC 2015+ 均完整支持
- 避免用
std::chrono::high_resolution_clock:标准只要求它是“尽可能高精度”,实际可能是system_clock别名(如旧版 GCC) - 注意
steady_clock::time_point不能直接输出,必须减法后转duration
示例:一个最小可运行的 wall time 测量片段
#include <chrono>
#include <iostream>
<p>int main() {
auto start = std::chrono::steady_clock::now();</p><pre class="brush:php;toolbar:false;">// 模拟一些工作
volatile int x = 0;
for (int i = 0; i < 1e8; ++i) x += i;
auto end = std::chrono::steady_clock::now();
auto seconds = std::chrono::duration<double>(end - start).count();
std::cout << "Wall time: " << seconds << " s\n";}
这个例子能跑通的关键点:不依赖任何外部库、不假设起始时间为 0、不打印未定义行为的 time_point 值。真正容易被忽略的是——如果把 start 和 end 声明在不同作用域(比如函数内部分支中),编译器可能因优化重排顺序,导致测量失真;务必保证它们在同一作用域、且中间无可能被优化掉的空操作。


















