boost::timer::cpu_timer的C++标准库等效方案是什么?
替代boost::timer::cpu_timer的C++标准库方案
好问题!确实,C标准库在很长一段时间里没有像boost::timer::cpu_timer那样能一站式获取墙钟、用户态、内核态时间的工具,但咱们有两种靠谱的解决方案——如果能升级到C20,直接用标准库就能搞定;要是还在用旧标准,也能通过平台相关API组合实现,最终输出格式和你要的完全一致。
C++20 标准原生方案
C++20引入了std::chrono::process_cpu_clock,这是专门为追踪进程CPU时间设计的时钟,它可以同时记录用户态CPU时间和内核态CPU时间。而墙钟时间(wall time)我们可以用std::chrono::steady_clock(它不受系统时间调整影响,比system_clock更适合计时场景)。
下面是完整的示例代码,输出格式和你给出的boost示例完全匹配:
#include <chrono> #include <iostream> #include <iomanip> int main() { // 记录起始时间点 const auto wall_start = std::chrono::steady_clock::now(); const auto cpu_start = std::chrono::process_cpu_clock::now(); // ---------------------- // 这里替换成你要计时的代码 for (volatile int i = 0; i < 100000000; ++i); // ---------------------- // 记录结束时间点 const auto wall_end = std::chrono::steady_clock::now(); const auto cpu_end = std::chrono::process_cpu_clock::now(); // 计算各时间维度的时长(转换为秒,保留6位小数) using fsec = std::chrono::duration<double>; const fsec wall_duration = wall_end - wall_start; const auto user_duration = std::chrono::duration_cast<fsec>( std::chrono::process_cpu_clock::to_user(cpu_end - cpu_start) ); const auto system_duration = std::chrono::duration_cast<fsec>( std::chrono::process_cpu_clock::to_system(cpu_end - cpu_start) ); const auto total_cpu = user_duration + system_duration; const double cpu_percent = (total_cpu.count() / wall_duration.count()) * 100; // 格式化输出,和boost风格一致 std::cout << std::fixed << std::setprecision(6); std::cout << wall_duration.count() << "s wall, " << user_duration.count() << "s user + " << system_duration.count() << "s system = " << total_cpu.count() << "s CPU (" << std::setprecision(1) << cpu_percent << "%)" << std::endl; return 0; }
这段代码的核心是process_cpu_clock::to_user和to_system方法,它们能从CPU时间间隔中拆分出用户态和内核态的耗时,完美替代boost的功能。
C++11/17 兼容方案(平台相关)
如果你的项目还不能升级到C++20,也可以通过平台原生API来实现,核心思路是:用std::chrono::steady_clock获取墙钟时间,用平台API获取进程的用户态/内核态CPU时间。
Linux/macOS 平台
可以使用getrusage函数(来自<sys/resource.h>),它能获取当前进程的资源使用统计,包括用户态和内核态时间:
#include <chrono> #include <iostream> #include <iomanip> #include <sys/resource.h> #include <unistd.h> int main() { const auto wall_start = std::chrono::steady_clock::now(); struct rusage start_usage; getrusage(RUSAGE_SELF, &start_usage); // ---------------------- // 这里替换成你要计时的代码 for (volatile int i = 0; i < 100000000; ++i); // ---------------------- const auto wall_end = std::chrono::steady_clock::now(); struct rusage end_usage; getrusage(RUSAGE_SELF, &end_usage); // 计算墙钟时间 using fsec = std::chrono::duration<double>; const fsec wall_duration = wall_end - wall_start; // 计算用户态和内核态时间(rusage的时间单位是微秒) const double user_sec = (end_usage.ru_utime.tv_sec - start_usage.ru_utime.tv_sec) + (end_usage.ru_utime.tv_usec - start_usage.ru_utime.tv_usec) / 1e6; const double system_sec = (end_usage.ru_stime.tv_sec - start_usage.ru_stime.tv_sec) + (end_usage.ru_stime.tv_usec - start_usage.ru_stime.tv_usec) / 1e6; const double total_cpu = user_sec + system_sec; const double cpu_percent = (total_cpu / wall_duration.count()) * 100; // 格式化输出 std::cout << std::fixed << std::setprecision(6); std::cout << wall_duration.count() << "s wall, " << user_sec << "s user + " << system_sec << "s system = " << total_cpu << "s CPU (" << std::setprecision(1) << cpu_percent << "%)" << std::endl; return 0; }
Windows 平台
使用GetProcessTimes函数(来自<windows.h>),它能获取进程的创建时间、退出时间、内核态时间和用户态时间:
#include <chrono> #include <iostream> #include <iomanip> #include <windows.h> // 将FILETIME转换为秒数(FILETIME单位是100纳秒) double filetime_to_sec(FILETIME ft) { ULARGE_INTEGER ul; ul.LowPart = ft.dwLowDateTime; ul.HighPart = ft.dwHighDateTime; return static_cast<double>(ul.QuadPart) / 1e7; } int main() { const auto wall_start = std::chrono::steady_clock::now(); FILETIME create_time, exit_time, kernel_start, user_start; GetProcessTimes(GetCurrentProcess(), &create_time, &exit_time, &kernel_start, &user_start); // ---------------------- // 这里替换成你要计时的代码 for (volatile int i = 0; i < 100000000; ++i); // ---------------------- const auto wall_end = std::chrono::steady_clock::now(); FILETIME kernel_end, user_end; GetProcessTimes(GetCurrentProcess(), &create_time, &exit_time, &kernel_end, &user_end); // 计算墙钟时间 using fsec = std::chrono::duration<double>; const fsec wall_duration = wall_end - wall_start; // 计算用户态和内核态时间 const double user_sec = filetime_to_sec(user_end) - filetime_to_sec(user_start); const double system_sec = filetime_to_sec(kernel_end) - filetime_to_sec(kernel_start); const double total_cpu = user_sec + system_sec; const double cpu_percent = (total_cpu / wall_duration.count()) * 100; // 格式化输出 std::cout << std::fixed << std::setprecision(6); std::cout << wall_duration.count() << "s wall, " << user_sec << "s user + " << system_sec << "s system = " << total_cpu << "s CPU (" << std::setprecision(1) << cpu_percent << "%)" << std::endl; return 0; }
总结
- 如果项目支持C++20,优先使用
std::chrono::process_cpu_clock,这是标准、跨平台的解决方案。 - 旧标准下,根据目标平台选择对应的原生API,同样能实现和
boost::timer::cpu_timer完全一致的输出效果。
内容的提问来源于stack exchange,提问作者tommyk
相关产品推荐
相关产品推荐

