std::chrono::high_resolution_clock 不一定真“高精度”,因平台差异可能退化为毫秒级 system_clock;应优先使用 steady_clock,它保证单调且现代系统达纳秒级,并用 duration_cast 处理时长。

std::chrono::high_resolution_clock 为什么不一定真“高精度”
很多代码直接用 std::chrono::high_resolution_clock::now(),结果发现两次调用差值恒为 0 或跳变很大——这不是你代码写错了,而是这个类型在不同平台底层映射不同:high_resolution_clock 在 Windows 上通常等价于 steady_clock(基于 QueryPerformanceCounter),但在某些旧 Linux 内核或容器环境中,可能退化为 system_clock(依赖 gettimeofday),分辨率只有毫秒级。
- 实操建议:永远优先用
std::chrono::steady_clock,它保证单调、不回拨、且实际分辨率足够(现代系统基本是纳秒级) - 验证方法:运行
std::chrono::steady_clock::period::num / std::chrono::steady_clock::period::den,若输出是1和1000000000,说明是纳秒钟 - 别依赖
high_resolution_clock::is_steady的返回值做逻辑分支——C++ 标准只要求它“尽力而为”,不保证行为一致
计时区间必须用 duration_cast,不能靠 auto 推导隐式截断
常见错误是这样写:auto diff = end - start; 然后直接 std::cout ——<code>diff 类型是 std::chrono::nanoseconds(或更细粒度的内部表示),但 count() 返回的是底层整型,单位完全取决于模板参数。没显式转换就打印,容易误读成微秒甚至毫秒。
- 正确做法:用
std::chrono::duration_cast<:chrono::microseconds>(diff).count()</:chrono::microseconds>明确指定输出单位 - 注意:
duration_cast是向下取整(truncating),比如 1234ns 转microseconds得到 1μs;如需四舍五入,先加半格再 cast:duration_cast<microseconds>(diff + 500ns)</microseconds> - 避免用
auto存储时间点差值后反复 cast——每次 cast 都有轻微开销,尤其在 tight loop 里;一次性转成目标类型存变量更稳
跨线程或系统休眠时,steady_clock 仍可靠,system_clock 不行
如果你在测量一段网络请求耗时,或者等待某个条件变量唤醒,用 system_clock 可能拿到负数或异常大值——因为用户手动调时间、NTP 同步、休眠唤醒都会让系统时间跳变。steady_clock 完全不受这些影响,它只随 CPU 实际运行走。
- 适用场景:性能 benchmark、函数执行耗时、超时控制(如
std::this_thread::sleep_until内部就用 steady) - 不适用场景:日志打时间戳、计算“从 1970 年到现在多少秒”,这类必须用
system_clock - 警告:不要把
steady_clock::time_point和system_clock::time_point混着减——编译不过,而且语义错乱
Release 模式下空循环被优化导致计时为 0,怎么破
写了个小函数想测开销,结果 Release 下 duration_cast<nanoseconds>(end - start).count()</nanoseconds> 总是 0。不是 clock 不够快,是编译器把整个待测逻辑优化掉了,只留下两个 time_point 相减。
立即学习“C++免费学习笔记(深入)”;
- 简单 fix:把被测变量声明为
volatile,或用asm volatile("" ::: "memory")插内存栅栏(GCC/Clang) - 更靠谱的做法:把待测逻辑封装进函数,传参用
volatile指针,或让返回值参与后续不可省略的计算(比如累加到全局volatile int sink) - 额外提醒:别在计时块里用
std::cout或printf——IO 开销远大于目标逻辑,且会干扰编译器内联判断
真正难的不是调用哪个 now(),而是确保被测逻辑没被优化掉、单位没看错、时钟类型没混用。这几个点卡住,再准的纳秒钟也白搭。










