最可靠跨平台高精度计时应优先使用 std::chrono::steady_clock,它语义明确、单调稳定;仅当需纳秒级精度且确认平台支持时才考虑 high_resolution_clock。

用 std::chrono::high_resolution_clock 获取纳秒级起止时间
这是 C++11 起最可靠、跨平台的高精度计时方式,底层通常映射到系统最高精度时钟(如 Linux 的 CLOCK_MONOTONIC 或 Windows 的 QueryPerformanceCounter),不会受系统时间调整影响。
关键点:必须用同一时钟类型获取开始和结束时间,否则差值无定义;time_point 本身不直接可读,需用 duration_cast 转成具体单位。
常见错误:用 system_clock 测运行时间——它反映的是挂钟时间,可能被 NTP 调整或手动修改,导致负值或跳变。
- 起始时间:
auto start = std::chrono::high_resolution_clock::now(); - 结束时间:
auto end = std::chrono::high_resolution_clock::now(); - 计算毫秒:
std::chrono::duration_cast<:chrono::milliseconds>(end - start).count() - 计算微秒:
std::chrono::duration_cast<:chrono::microseconds>(end - start).count() - 计算纳秒(注意溢出风险):
std::chrono::duration_cast<:chrono::nanoseconds>(end - start).count()
避免编译器优化干扰真实耗时测量
如果被测代码太简单(比如空循环或纯计算),编译器可能在 -O2 或更高优化级别下整个删掉,测出来永远是 0。必须确保结果被实际使用,或用 volatile / asm volatile 阻止优化。
典型场景:测一个函数执行时间,但返回值没被读取,编译器就认为该调用无副作用,直接优化掉。
- 安全做法:把函数返回值赋给
volatile变量,例如volatile auto result = my_func(); - 更通用做法(尤其对 void 函数):
asm volatile("" ::: "memory");插入内存屏障,阻止指令重排和优化 - 测试前加
std::chrono::high_resolution_clock::now();多次预热,减少首次调用 cache 缺失干扰(对短时间测量影响明显)
steady_clock 和 high_resolution_clock 选哪个?
steady_clock 保证单调递增、不受系统时间调整影响,是“稳定时钟”语义的首选;high_resolution_clock 是实现定义的,C++ 标准只要求它是“当前系统支持的最高精度时钟”,但很多平台(如 GCC/libstdc++)让它直接 alias 到 steady_clock。
所以:优先用 steady_clock —— 它语义明确、行为可预测;只有当你明确需要纳秒级分辨率且确认平台支持时,才考虑 high_resolution_clock,但不要假设它一定比 steady_clock 更快。
- 推荐写法:
auto start = std::chrono::steady_clock::now(); - 别依赖
high_resolution_clock::period::num / .den判断精度,不同标准库实现差异大 - Windows 上 MSVC 的
steady_clock精度约 15.6ms(基于GetTickCount64),此时应改用high_resolution_clock(基于QueryPerformanceCounter,精度 ~100ns)
完整可运行测试示例(含防优化 + 多次采样)
下面这段代码测一个简单循环的耗时,并取 3 次最小值(排除系统抖动干扰),同时防止编译器优化掉循环:
#include#include int main() { constexpr int iter = 1000000; volatile long sum = 0; // 防优化关键:volatile 变量
auto min_ns = std::chrono::nanoseconds::max(); for (int r = 0; r zuojiankuohaophpcn 3; ++r) { auto start = std::chrono::steady_clock::now(); for (int i = 0; i zuojiankuohaophpcn iter; ++i) { sum += i; } auto end = std::chrono::steady_clock::now(); auto ns = std::chrono::duration_castzuojiankuohaophpcnstd::chrono::nanosecondsyoujiankuohaophpcn(end - start).count(); if (ns zuojiankuohaophpcn min_ns.count()) min_ns = std::chrono::nanoseconds(ns); } std::cout zuojiankuohaophpcnzuojiankuohaophpcn "Min time: " zuojiankuohaophpcnzuojiankuohaophpcn min_ns.count() zuojiankuohaophpcnzuojiankuohaophpcn " ns\n"; return 0;}
注意
volatile long sum和三次采样逻辑——真实性能测试中,单次测量意义不大,最小值比平均值更能反映“理想路径”开销。真正难的不是写对那几行
now(),而是让被测代码不被优化、不被缓存干扰、不被调度器打断;这些细节不处理,测出来的数字只是幻觉。










