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

如何用 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);- 用字面量后缀(
ms、us、ns)比写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_point 和 system_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_clock 比 high_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_point和system_clock::time_point之间不能直接相减
实际写压测或延迟打点时,最容易忽略的是 clock 类型选择和 time_point 转换路径——这两处一错,整个测量就失去意义。