生产环境必须用std::chrono::steady_clock测时间差,因其单调递增不随系统时间调整;起始结束均调用now()得time_point,相减得duration,转整数毫秒需用duration_cast并防溢出截断。

用 std::chrono::steady_clock 获取稳定时间差
直接用 std::chrono::system_clock 会有风险——系统时间可能被手动调整或 NTP 同步跳变,导致算出负增量或突增。生产环境必须用 std::chrono::steady_clock,它不随系统时间变化,只单调递增。
实操建议:
- 起始和结束都调用
std::chrono::steady_clock::now(),返回time_point - 两
time_point相减得到duration,类型是模板化的,比如nanoseconds、milliseconds - 别用
clock_gettime(CLOCK_MONOTONIC, ...)手动封装,steady_clock在主流平台(Linux/macOS/Windows)底层就是它
把 duration 转成整数毫秒要小心溢出和截断
duration_cast 是关键,但默认向下取整(丢弃小数部分),且若目标类型容量不够会编译失败或运行时未定义行为。
常见错误现象:用 auto ms = duration_cast<milliseconds>(dur).count()</milliseconds> 得到负值或极大正数——其实是 count() 返回的 long long 被隐式转成 int 溢出了。
使用场景和参数差异:
- 测函数耗时(通常 duration_cast
或 microseconds,count()接long long - 测长周期任务(如分钟级):优先用
duration_cast<seconds></seconds>,避免中间累积误差 - 需要带小数的浮点毫秒:写
duration_cast<duration milli>>(dur).count()</duration>,不推荐用于性能敏感路径
在循环里反复计时容易误测 CPU 缓存/分支预测效应
单纯包一层 steady_clock::now() 测单次函数调用,结果波动大、不可靠。真实性能分析得排除干扰。
实操建议:
- 预热:先调用几次目标函数,让代码进指令缓存、数据进 L1 cache
- 多轮采样:执行 N 次(比如 10000),取中位数或平均值,别只跑一次
- 关中断干扰(仅 Linux root):临时
echo 1 > /proc/sys/kernel/perf_event_paranoid可能改善,但通常没必要 - 别在
std::cout或日志里直接打时间戳——IO 本身开销远超被测逻辑
跨线程共享 time_point 不需要额外同步
time_point 是值类型,内部只是个整数计数器(rep),拷贝安全。多个线程各自调用 now() 也没问题——每个线程拿到的是该时刻的快照。
但要注意:
- 不同线程的
now()调用之间没有顺序保证,不能靠它推断事件先后(要用std::atomic_thread_fence或锁) - 如果要把一个线程的
time_point传给另一个线程做差值计算,没问题;但别假设两个线程“同时”调用now()会返回相同值——硬件时钟分辨率有限(通常几十纳秒) - 某些嵌入式平台的
steady_clock可能精度低(如 1ms),需查steady_clock::period::num / steady_clock::period::den
最常被忽略的是时钟精度和测量上下文:你以为测的是算法,其实测的是 TLB miss 或 page fault;以为单位是毫秒,实际 count() 是纳秒但你用了 int 截断。动手前先看 steady_clock::is_steady 和 period。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











