std::chrono::high_resolution_clock是标准库中唯一能稳定提供纳秒级时间戳的时钟,实际分辨率依赖硬件与内核,但支持纳秒单位运算,适用于高精度差值计算。

用 std::chrono::high_resolution_clock 获取纳秒级时间戳
标准库中能稳定提供纳秒级精度的只有 std::chrono::high_resolution_clock,它在大多数现代系统(Linux/Windows/macOS)上底层会映射到 CLOCK_MONOTONIC 或 QueryPerformanceCounter,不是所有平台都真正返回纳秒——实际分辨率取决于硬件和内核,但类型支持纳秒单位运算,足够用于差值计算。
关键点:别用 std::chrono::system_clock(带时区、可能跳变),也别用 std::chrono::steady_clock(虽单调但部分旧编译器实现分辨率仅毫秒)。
实操建议:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 始终用
.time_since_epoch().count()提取整数计数值,再根据duration类型推导单位(例如nanoseconds的count()就是纳秒数) - 两次
now()调用之间避免函数调用开销干扰测量,尤其不要在计时区间内打日志或分配内存 - 单次测量意义有限,建议循环多次取最小值或中位数,抵消调度抖动
正确构造纳秒级差值:用 duration_cast 而非强制类型转换
直接对 time_point 做减法得到的是 duration,但它默认单位不一定是纳秒。比如 high_resolution_clock::now() - start 可能返回 nanoseconds,也可能返回 microseconds(取决于实现),硬转 long long 会丢精度或溢出。
立即学习“C++免费学习笔记(深入)”;
实操建议:
- 显式用
std::chrono::duration_cast<:chrono::nanoseconds>(end - start)</:chrono::nanoseconds>转换,确保拿到纳秒整数 - 如果只需要高精度相对值,直接用
(end - start).count()并配合decltype(end - start)::period::num / decltype(end - start)::period::den判断实际单位(但通常没必要) - 避免写
auto diff = end - start; long ns = diff.count();——count()返回的是“滴答数”,不是纳秒,除非你知道当前duration的period是std::nano
Windows 下 QueryPerformanceCounter 的兼容性陷阱
虽然 std::chrono::high_resolution_clock 在 MSVC 和较新 MinGW 中已基本可靠,但某些老旧环境(如 Windows 7 + VC2013)下其 period::den 可能为 10⁷(即 100 纳秒),导致 duration_cast<nanoseconds></nanoseconds> 向上取整失真;此时手撸 QueryPerformanceCounter 反而更可控。
实操建议:
- 若必须手动调用,先用
QueryPerformanceFrequency(&freq)检查是否 > 0,再算(end.QuadPart - start.QuadPart) * 1'000'000'000 / freq.QuadPart - 注意
freq.QuadPart通常是 10⁷ 量级(如 3,125,000),直接整除会截断,务必用__int128或先乘后除防溢出(64 位乘法易溢出) - 除非维护遗留代码,否则优先坚持用
std::chrono—— 手动方案跨平台成本高,且 Win11 已优化high_resolution_clock表现
测量短代码段时,编译器优化会导致结果为 0
如果被测代码太短(比如几个加法),GCC/Clang/MSVC 在 -O2 下可能整个优化掉,start 和 end 时间差为 0;或者指令重排让计时点错位。
实操建议:
- 用
volatile或asm volatile("" ::: "memory")阻止编译器乱动(后者更便携) - 把待测逻辑封装成函数,传入
volatile参数或返回值,防止内联后被削掉 - 加循环(如 1000 次)再除以次数,但注意循环本身开销也要扣除——可测空循环耗时作 baseline
- 用
std::chrono::nanoseconds::min()判断是否真为 0,而不是靠打印看“0”
真正难的不是拿到纳秒数字,而是让这个数字反映你想要的那部分执行行为——缓存预热、分支预测、TLB 命中、甚至 CPU 频率升降都会影响结果。同一段代码跑十次,可能有 2–3 倍差异。别只信单次输出。

















