c++oding="utf-8" ?>
std::chrono::steady_clock 是唯一靠谱选择,因其在各平台稳定映射到可靠单调时钟源、is_steady == true、不受系统时间调整影响;应避免 system_clock 和 high_resolution_clock。

为什么 std::chrono::steady_clock 是唯一靠谱选择
Windows 的 QueryPerformanceCounter 和 Linux 的 clock_gettime(CLOCK_MONOTONIC, ...) 行为不一致,手动封装容易漏掉时钟源漂移、系统休眠跳变、跨进程精度丢失等问题。C++11 起,std::chrono::steady_clock 在主流编译器(MSVC / GCC / Clang)下已稳定映射到各平台最可靠的单调时钟源,且保证 is_steady == true —— 这意味着它不随系统时间调整而跳变,也不受 NTP 校正影响,天然适合微秒级间隔测量。
注意:别用 std::chrono::system_clock,它对应系统时间,可能因 NTP 或用户修改而倒流或突跳;也别信某些博客推荐的 std::chrono::high_resolution_clock,它的 is_steady 在部分旧版 libstdc++ 上为 false,行为不可靠。
如何正确获取微秒级时间差(避免整数溢出和精度截断)
直接调用 time_point.time_since_epoch().count() 返回的是纳秒或更粗粒度的整数,不同平台底层 tick 周期不同(如 Windows 通常是 100ns,Linux 可能是 1ns),硬转 long long 微秒易丢精度或溢出。正确做法是统一用 duration_cast 转换:
auto start = std::chrono::steady_clock::now(); // ... work ... auto end = std::chrono::steady_clock::now(); auto us = std::chrono::duration_cast<:chrono::microseconds>(end - start).count(); </:chrono::microseconds>
- 必须用
duration_cast,不能用static_cast或隐式转换,否则可能触发未定义行为 -
count()返回的是有符号整数(rep类型),在长时间运行计时中注意是否超出int64_t范围(约 292 年才溢出,一般不用管) - 若需更高精度(比如纳秒),改用
std::chrono::nanoseconds,但要注意输出设备(如 printf)对纳秒值的支持
跨平台高精度 sleep 的陷阱:别依赖 std::this_thread::sleep_for
虽然 std::this_thread::sleep_for(std::chrono::microseconds(1)) 看似能实现微秒级等待,但实际精度由 OS 调度器决定:Windows 默认调度周期是 15.6ms,Linux 默认也是 10ms 量级。即使你传入 1μs,真实休眠时间往往是 10–15ms,且无法保证唤醒及时性。
如果你真需要 sub-millisecond 级别的 busy-wait 控制(例如硬件同步),只能自己轮询 + std::chrono::steady_clock 比较:
auto start = std::chrono::steady_clock::now(); auto target = start + std::chrono::microseconds(50); while (std::chrono::steady_clock::now()
- 纯轮询会吃满一个 CPU 核,务必评估功耗和干扰
- Windows 上可调用
timeBeginPeriod(1)缩短系统调度粒度,但需管理员权限且影响全局,不推荐 - Linux 上可通过
sudo sysctl -w kernel.timer_migration=0和chrt -f 99提升实时性,仍不能替代硬件级方案
Release 模式下计时结果异常?检查编译器优化和空循环消除
写测试代码时常见这种写法:
auto t1 = std::chrono::steady_clock::now(); for (int i = 0; i <p>在 <code>-O2</code> 下,整个循环可能被完全优化掉,导致测出的时间接近 0。解决方法:</p>
- 把被测逻辑的输入/输出标记为
volatile,或用asm volatile("" ::: "memory")插入内存屏障 - 确保被测函数有可观测副作用(如写全局变量、调用
printf) - 更稳妥的做法:用
std::chrono::steady_clock::now()包裹实际不可省略的计算,例如加密、memcpy、矩阵运算等
微秒计时本身很轻量,但“测什么”比“怎么测”更容易出错——尤其当逻辑被优化、缓存预热未做、CPU 频率动态缩放未锁定时,单次测量意义有限。真要压测,得跑几百次取最小值或中位数,还得关掉 Turbo Boost 和后台进程。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











