std::chrono::high_resolution_clock不保证高精度,实际分辨率取决于系统;测短于1ms耗时应避免使用,推荐steady_clock并重复多次取平均。

std::chrono::high_resolution_clock 真的高精度吗?
它不保证高精度,只表示“当前平台能提供的最高分辨率”,实际精度取决于操作系统和硬件。Windows 上常见是 15.6ms(默认系统定时器间隔),Linux 可能是 1–10ns(取决于 CLOCK_MONOTONIC 实现),但用户态程序无法突破内核调度粒度。
- 别用
std::chrono::high_resolution_clock::now()测短于 1ms 的耗时——结果大概率是 0 或跳变值 - 想测函数执行时间,至少重复执行 1000+ 次再取平均,否则噪声远大于信号
- Windows 下可调用
timeBeginPeriod(1)(需Winmm.lib)临时提频系统定时器,但会影响全系统功耗,仅调试用
测单次函数耗时该用哪个 clock?
优先选 std::chrono::steady_clock:单调、不回拨、适合间隔测量;high_resolution_clock 在部分 MSVC 版本里只是 steady_clock 的别名,别依赖它一定“更高”。
- 避免用
system_clock——它映射系统时间,可能因 NTP 调整跳变,测耗时不安全 - 实操写法:
auto start = std::chrono::steady_clock::now(); do_work(); auto end = std::chrono::steady_clock::now(); auto us = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
- 注意
duration_cast截断不四舍五入,要纳秒级精度就别 cast 到微秒再除
为什么两次 now() 相减总是 0?
不是代码写错了,是你的操作本身太快,低于时钟分辨率。比如空循环、访问缓存命中的变量、编译器优化掉的代码,都可能被测出 0。
- 关掉优化(
-O0)再试,否则do_work()可能被整个优化掉 - 强制防止编译器优化:把输入/输出变量标为
volatile,或用asm volatile("" ::: "memory")插内存屏障 - 检查是否在 Debug 模式下运行——Release 下指令重排更激进,反而可能让耗时“看起来更短”
跨平台计时封装要注意什么?
不同平台的 steady_clock 底层来源不同:Linux 用 CLOCK_MONOTONIC,Windows 用 QueryPerformanceCounter,macOS 用 mach_absolute_time。差异主要在初始化开销和首次调用延迟。
立即学习“C++免费学习笔记(深入)”;
- 不要在高频循环里反复调用
now()——每次调用都有函数跳转+系统调用开销(尤其 Windows) - 如果做性能监控,建议用 RAII 封装:
struct Timer { auto start = steady_clock::now(); ~Timer() { /* log diff */ } }; - 注意 C++20 前没有统一的纳秒级输出格式,
duration.count()返回的是带符号整数,溢出风险比想象中高(比如 64 位纳秒数 292 年才满)
实际写计时逻辑时,最常被忽略的是「测量目标是否真的被执行」——编译器优化、CPU 分支预测、缓存预热、TLB miss 都会扭曲结果。真要准,得控制变量,而不是换一个 clock 类型。










