C++中的std::chrono库是什么?(如何高精度测量程序性能)

3次阅读

能,但实际精度受硬件和系统调度限制;std::chrono::high_resolution_clock通常支持纳秒级时间点,分辨率需通过period::num/den验证,单次测量无效,须多次循环取最小值,并用volatile或asm防止优化干扰。

C++中的std::chrono库是什么?(如何高精度测量程序性能)

std::chrono 能不能测到纳秒级?

能,但实际精度取决于硬件和系统调度,std::chrono::high_resolution_clock 通常提供纳秒级时间点,但返回的 time_point 分辨率不等于你真能稳定测出纳秒差异。windows 上它常退化为毫秒级(尤其在旧版 MSVC 或虚拟机里),linux 下用 CLOCK_MONOTONIC 一般能到微秒甚至纳秒,但连续两次调用差值可能仍是 10–15 纳秒起步。

实操建议:

立即学习C++免费学习笔记(深入)”;

  • 别直接信 time_since_epoch().count() 的数值位数——先查分辨率:std::chrono::high_resolution_clock::period::num / std::chrono::high_resolution_clock::period::den
  • 单次测量毫无意义;必须循环多次(比如 10000 次)取最小值或中位数,排除调度抖动、缓存预热等干扰
  • 避免用 std::chrono::system_clock 测性能——它可能被 NTP 调整,导致负差值或跳变

怎么写一个靠谱的函数耗时测量片段?

核心是“隔离 + 重复 + 防优化”,不是套个 start/end 就完事。编译器可能把空循环、无副作用函数整个删掉,CPU 可能乱序执行,测量代码本身也得进 cache 热路径。

实操建议:

立即学习C++免费学习笔记(深入)”;

  • volatileasm volatile("" ::: "memory") 阻止编译器重排和优化关键段
  • 把待测函数封装成接受 volatile 参数或返回 volatile 结果,确保不被优化掉
  • 示例结构:
    auto start = std::chrono::high_resolution_clock::now();<br>for (int i = 0; i < N; ++i) {<br>    result = foo(data[i]);<br>    asm volatile("" ::: "memory"); // 内存栅栏<br>}<br>auto end = std::chrono::high_resolution_clock::now();

std::chrono::duration_cast 为什么有时结果为 0?

因为目标单位比源 duration 的 tick 更大,且原始值没跨过一个整 tick。比如用 nanoseconds 存了 500 纳秒,再 duration_cast<microseconds></microseconds> 就得 0——这不是 bug,是向下取整语义。

常见错误现象:

  • 测出函数耗时总是 0ms,其实是用了 duration_cast<milliseconds></milliseconds>,但真实耗时只有几微秒
  • 不同平台下结果不一致:Clang 可能默认用更高分辨率时钟,GCC 在某些配置下 high_resolution_clock 实际是 steady_clock,分辨率较低
  • 正确做法:优先用 duration_cast<nanoseconds></nanoseconds>duration_cast<microseconds></microseconds>,再除以 1000.0 得毫秒浮点值,而不是强转 milliseconds

Linux 下 gettimeofday 和 std::chrono 哪个更准?

gettimeofday 已废弃,精度上限是微秒,且非单调(受时钟调整影响);std::chrono::high_resolution_clock 在现代 libstdc++/libc++ 中底层调用 clock_gettime(CLOCK_MONOTONIC),更可靠。

但要注意:

  • 某些老版本 GCC(如 4.8)的 libstdc++ 把 high_resolution_clock 实现为 system_clock,失去单调性
  • 若需最大兼容性和明确语义,可直接用 clock_gettime(CLOCK_MONOTONIC, &ts),然后自己构造 nanoseconds,绕过 std::chrono 的实现差异
  • glibc 2.17+ 支持 CLOCK_MONOTONIC_RAW,避开 NTP 频率校正,适合超精密场景,但 std::chrono 不暴露这个 clock

真正难的不是调哪个函数,而是理解你测的到底是什么:是 CPU 时间?墙上时间?是否包含系统调用等待?这些不会自动帮你区分。

text=ZqhQzanResources