能,getprocesstimes 可获取当前进程内核态与用户态总 cpu 时间,单位为 100 纳秒(filetime),需转为毫秒时用 int64_t 转换后除以 10000.0,仅限 windows,须确保进程句柄权限正确。

GetProcessTimes 能否获取当前进程的 CPU 时间?
能,但要注意它返回的是内核态 + 用户态的总 CPU 时间,单位是 100 纳秒(即 FILETIME),不是秒或毫秒。它不区分线程,是整个进程生命周期内累计的 CPU 占用时间,且只在 Windows 平台有效。
常见错误是直接把 GetProcessTimes 返回的 FILETIME 当作毫秒数用,结果得到一个巨大无意义的整数(比如 133245678901234)——那是 100 纳秒计数,需转换。
-
GetProcessTimes必须传入当前进程的句柄,GetCurrentProcess()是安全的,别用OpenProcess开错权限(至少要PROCESS_QUERY_INFORMATION) - 四个
FILETIME*参数中,只有lpCreationTime、lpExitTime、lpKernelTime、lpUserTime有效;lpExitTime对运行中进程为 0 - 返回值为
FALSE时,用GetLastError()查错,常见是权限不足或句柄无效
如何把 FILETIME 转成毫秒级 double?
FILETIME 是 64 位整数,低 32 位 + 高 32 位组合表示自 1601-01-01 UTC 起的 100 纳秒数。CPU 时间差值不需要转绝对时间,只需做减法再缩放:
LARGE_INTEGER li; li.LowPart = ft.dwLowDateTime; li.HighPart = ft.dwHighDateTime; double ms = li.QuadPart / 10000.0; // 100 ns → ms
注意:不能用 ULARGE_INTEGER 直接赋值再除,因为 ULARGE_INTEGER 是无符号,若高位非零而你用有符号上下文(如某些调试器显示),可能误判为负值。稳妥做法是统一用 LARGE_INTEGER 或强制转 int64_t:
- 推荐写法:
int64_t t = ((int64_t)ft.dwHighDateTime - 然后
t / 10000.0得到毫秒(double) - 若只要整数毫秒,用
t / 10000,但注意截断而非四舍五入
为什么两次 GetProcessTimes 相减结果几乎为 0?
因为 CPU 时间增长极慢——普通空循环几万次也才增加不到 0.1ms。如果没做足够重的计算或阻塞调用,两次采样间隔内进程根本没获得多少调度时间片。
- 验证方法:在两次调用之间插入密集计算,比如
volatile int x = 0; for(int i=0; i - 或者调用
Sleep(100)后再测——你会发现KernelTime和UserTime几乎不变,因为 Sleep 是让出 CPU,不消耗时间 - 真正耗 CPU 的操作:数学运算、内存拷贝(
memcpy大块数据)、加密哈希等 - 注意:优化等级(/O2)可能导致编译器把空循环整个删掉,加
volatile或输出到全局变量可抑制
跨平台替代方案:clock() 和 std::chrono::steady_clock 区别在哪?
clock() 在 Windows 上实际调用的就是 GetProcessTimes 的用户态部分(lpUserTime),所以它只反映用户态 CPU 时间,且精度低(常为 10–15ms)。而 std::chrono::steady_clock 是单调递增的 wall-clock,和 CPU 时间无关。
- 想严格测 CPU 时间:Windows 用
GetProcessTimes,Linux/macOS 用clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ...) -
std::chrono::high_resolution_clock在 Windows 上通常等价于QueryPerformanceCounter,仍是 wall-clock,不是 CPU 时间 - 没有标准 C++ 接口能直接跨平台获取进程 CPU 时间,必须条件编译
真正容易被忽略的是:CPU 时间是调度器统计的近似值,受系统负载、超线程、频率缩放影响,两次测量差值小于 1ms 时基本不可信;若需高精度分析,应重复采样取中位数,并排除 I/O 等阻塞行为干扰。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











