不能。GetProcessTimes返回的是进程自创建以来的累计CPU时间(内核态+用户态,100纳秒单位),并非“启动CPU耗时”;它无法分离冷启动阶段的初始化开销,也不能反映真实Wall-clock启动时长,后者需用lpCreationTime与当前系统时间差计算。

GetProcessTimes 能否获取“启动CPU耗时”?
不能。这是最常见的误解:GetProcessTimes 返回的是内核态 + 用户态的**累计 CPU 时间**(即进程自创建以来总共占用 CPU 的时长),不是“从启动到现在的 Wall-clock 时间”,更不是“启动过程的 CPU 耗时”。它不反映进程冷启动阶段的初始化开销(如 DLL 加载、TLS 初始化、CRT 构造等),那些时间大多发生在用户态代码执行前,但已被计入 lpUserTime 或 lpKernelTime —— 只是无法单独剥离。
如何用 GetProcessTimes 获取累计 CPU 时间
调用前需注意 HANDLE 权限和进程状态:
- 必须用
PROCESS_QUERY_INFORMATION权限打开目标进程(当前进程可用GetCurrentProcess()) - 返回的
FILETIME是 100 纳秒为单位的 64 位整数,需转为毫秒或秒才易读 - 若进程已退出,
GetProcessTimes仍可成功返回(只要句柄有效),但值不再更新
示例(获取当前进程累计 CPU 时间):
FILETIME ftCreate, ftExit, ftKernel, ftUser;
if (GetProcessTimes(GetCurrentProcess(), &ftCreate, &ftExit, &ftKernel, &ftUser)) {
ULARGE_INTEGER uiKernel = { ftKernel.dwLowDateTime, ftKernel.dwHighDateTime };
ULARGE_INTEGER uiUser = { ftUser.dwLowDateTime, ftUser.dwLowDateTime };
DWORD64 total_ms = (uiKernel.QuadPart + uiUser.QuadPart) / 10000; // 转毫秒
}
想测“启动到此刻”的真实耗时,该用什么?
要测进程从操作系统开始调度执行(即进入入口点)到当前时刻的 Wall-clock 时间,应结合 GetProcessTimes 的 lpCreationTime 和 GetSystemTimeAsFileTime:
立即学习“C++免费学习笔记(深入)”;
-
lpCreationTime是进程被创建的系统时间戳(高精度,UTC) - 用
GetSystemTimeAsFileTime获取当前时间,两者相减即得真实运行时长(非 CPU 占用) - 注意:这个差值包含所有挂起、等待、I/O 阻塞时间,不是 CPU 时间
关键点:别把 lpCreationTime 当成“启动完成时间”——它只是内核创建 EPROCESS 对象的时间,早于 main() 执行,但对绝大多数应用已足够接近。
容易被忽略的兼容性与精度陷阱
GetProcessTimes 在 Windows XP SP2+ 全平台可用,但有两处实操细节常踩坑:
- 32 位程序在 WoW64 下调用时,
FILETIME值完全正确,但若手动拼接dwLowDateTime/dwHighDateTime时用了错误的ULARGE_INTEGER初始化(比如只赋了.LowPart),会导致高位丢失 - 两次调用间隔极短(lpKernelTime 和
lpUserTime可能不变——Windows 内核只在调度周期(通常 ~15ms)更新这些计数器,不是实时采样 - 如果进程刚启动且尚未触发任何线程调度(比如卡在 loader lock 中),首次调用可能返回全 0 的
FILETIME(罕见但存在)
真正需要“启动性能分析”的场景,建议直接用 ETW(Event Tracing for Windows)捕获 ImageLoad、ProcessStart、ThreadStart 等事件,GetProcessTimes 只适合粗粒度监控。


















