c++中如何使用chrono库_c++高精度时间测量与转换方法【详解】

12次阅读

用 std::chrono::high_resolution_clock::now() 获取高精度时间点,性能测量只存 time_point,用 duration_cast 转换差值,转本地时间需经 system_clock 中转。

c++中如何使用chrono库_c++高精度时间测量与转换方法【详解】

如何用 std::chrono 获取当前高精度时间点

直接用 std::chrono::high_resolution_clock::now() 是最常用也最可靠的方式,它返回一个 time_point,底层精度取决于系统(linux 通常纳秒级,windows 可能是 100ns 级)。别用 system_clock 做性能测量——它可能被系统时钟调整影响,测出来的时间差会跳变。

常见错误:把 now() 结果直接转成 time_t 或打印为字符串来“看时间”,这反而丢精度、加开销。性能测量阶段只该存 time_point,最后再统一转换。

  • 不要写 auto t = std::chrono::system_clock::now(); 测耗时
  • 避免在循环里反复调用 .time_since_epoch().count() ——先存 time_point,结束再算差值
  • 线程测量时注意:不同 CPU 核心的 high_resolution_clock 可能有微小漂移,短于 1μs 的测量慎用

如何计算两个时间点之间的毫秒/微秒差值

std::chrono::duration_cast 转换,不是手动除 1000 或 1000000。c++ 的 duration 类型自带单位语义,硬除会丢失类型安全,还容易因整数截断出错。

auto start = std::chrono::high_resolution_clock::now(); // ... do something ... auto end = std::chrono::high_resolution_clock::now(); 

auto us = std::chrono::duration_cast(end - start); auto ms = std::chrono::duration_cast(end - start); std::cout << "cost: " << us.count() << " μsn";

注意:duration_cast 默认向下取整(如 1.9ms → 1ms),若需四舍五入,得手动加半格再 cast:

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

  • auto ms_rounded = std::chrono::duration_cast<:chrono::milliseconds>(end - start + 500μs);
  • 用字面量后缀(msusns)比写 std::chrono::milliseconds(1) 更简洁且不易错
  • 别对 duration 做浮点运算后再 cast——double 表示大整数时会丢失精度(比如超过 2⁵³ 的纳秒值)

如何把 time_point 转成可读的本地时间字符串

必须经过 system_clock 中转,因为 high_resolution_clock 不保证和日历时间对齐。直接用 high_resolution_clock::to_time_t 是未定义行为。

auto tp = std::chrono::high_resolution_clock::now(); auto sys_tp = std::chrono::system_clock::from_time_t(     std::chrono::system_clock::to_time_t(         std::chrono::time_point_cast(             tp         )     ) ); auto tt = std::chrono::system_clock::to_time_t(sys_tp); std::cout << std::put_time(std::localtime(&tt), "%Y-%m-%d %H:%M:%S");

这段代码看着绕,是因为 high_resolution_clock::time_pointsystem_clock::time_point 的 epoch(起始点)可能不同,不能直接 static_cast。实际项目中,如果只要“大致时间”,更稳妥的做法是测完耗时后,另起一次 system_clock::now() 打日志。

  • 别试图用 high_resolution_clock::to_time_t(tp) ——标准没定义它的行为
  • std::put_time 需要 C++11 以上且编译器支持,MSVC 2015+、GCC 5+、Clang 3.7+ 没问题
  • 多线程std::localtime 不安全,应改用 std::localtime_r(POSIX)或 std::localtime_s(MSVC)

为什么 steady_clockhigh_resolution_clock 更适合性能测量

因为 steady_clock 保证单调递增、不受系统时间调整影响,而 high_resolution_clock 在某些平台(尤其是旧版 windows)其实是 system_clock 的别名,一旦 NTP 同步或用户手动改系统时间,前后两次 now() 相减可能得到负值。

所以真正做 benchmark 或 latency 统计,优先用:

auto start = std::chrono::steady_clock::now(); // ... work ... auto end = std::chrono::steady_clock::now(); auto ns = std::chrono::duration_cast(end - start);
  • steady_clock 的精度不一定比 high_resolution_clock 低——现代 Linux 上两者常是同一实现
  • 检查是否真的单调:std::chrono::steady_clock::is_steady 返回 true 才放心用
  • 不要混用 clock 类型:steady_clock::time_pointsystem_clock::time_point 之间不能直接相减

实际写压测或延迟打点时,最容易忽略的是 clock 类型选择和 time_point 转换路径——这两处一错,整个测量就失去意义。

text=ZqhQzanResources