std::chrono::high_resolution_clock 不保证纳秒精度,实际分辨率取决于平台:linux 通常可达纳秒,windows 老版本可能仅毫秒;需实测最小时间差,避免虚拟机干扰,性能测量应使用 steady_clock,纳秒值须用 int64_t 等整数存储以防 double 精度丢失。

std::chrono::high_resolution_clock 真的能到纳秒?
不能直接依赖 std::chrono::high_resolution_clock::now() 返回纳秒值就认为你拿到了纳秒级精度。它的底层实现由平台决定:Linux 上通常映射到 clock_gettime(CLOCK_MONOTONIC),分辨率可达纳秒;Windows 上在较老版本可能退化为毫秒级(尤其 pre-Vista 或未启用高精度计时器)。实际可用精度得测,不是声明了 nanoseconds 就真有。
- 用
std::chrono::high_resolution_clock::period::num和den查真实周期,比如1/1000000000表示理论纳秒,但1/10000000就是 100ns - 连续调用两次
now(),看最小可测时间差(loop 测 1000 次取 min),这才是你机器上真正能分辨的下限 - 避免在虚拟机里测——很多 hypervisor 会把
CLOCK_MONOTONIC虚拟化成低频 tick,实测可能只有 10–15ms 分辨率
别用 system_clock 做性能基准
std::chrono::system_clock 是挂钟,受 NTP 调整、时区切换、手动改系统时间影响,两次 now() 相减可能为负或跳变。性能监控必须用单调时钟,只增不减。
- 始终选
std::chrono::steady_clock或high_resolution_clock(后者在多数现代系统等价于前者) -
system_clock适合打日志时间戳,不适合duration_cast<nanoseconds>(end - start).count()</nanoseconds> - Clang/GCC 下
steady_clock通常基于clock_gettime(CLOCK_MONOTONIC);MSVC 在 Win10+ 也默认用QueryPerformanceCounter,基本可靠
纳秒值怎么存?别用 double 或 float
纳秒级计数器增长极快:1 秒 = 1e9 ns,1 小时 ≈ 3.6e12 ns。用 double 存纳秒值,在 2^53 ≈ 9e15 之后就会丢失精度——约 10 天后,相邻整数纳秒无法区分。
- 一律用整数类型:推荐
int64_t(覆盖 ±292 年),或uint64_t(0 到 584 年) - 用
duration_cast<nanoseconds>(d).count()</nanoseconds>拿整数纳秒,不是duration_cast<nanoseconds>(d).operator double()</nanoseconds> - 如果要算均值或方差,先用整数累加所有纳秒值,最后再转浮点除法,避免中间步骤精度污染
短函数测量容易被编译器优化掉
写个空循环测 foo() 耗时,foo 可能被整个内联 + 消除,结果测出 0ns。这不是时钟不准,是代码没跑。
立即学习“C++免费学习笔记(深入)”;
- 强制防止优化:对输入用
volatile或asm volatile("" ::: "memory")内存栅栏 - 更稳妥的是让函数返回值参与后续不可省略的计算,比如写入全局
volatile int sink - 单次调用太短?用循环重复执行 N 次,再除以 N —— 但注意要确保 N 不被编译器当成常量折叠(比如从 runtime 输入读 N)
- 别忘了预热:首次调用可能触发 TLB / cache / 分支预测初始化,前几次样本丢弃更稳
真正难的不是拿到纳秒数字,而是让这串数字反映你本意想测的那个操作。时钟只是工具,它不会替你隔离干扰项。











