商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > C++如何获取当前进程的启动CPU耗时 _ GetProcessTimes实战【实战】

C++如何获取当前进程的启动CPU耗时 _ GetProcessTimes实战【实战】

  发布于2026-07-06 阅读(0)

扫一扫,手机访问

不能。要给出最直接的结论:不能。这也是很多开发者刚接触这个函数时最容易踩的坑。 `GetProcessTimes` 记录的,是进程自创建以来,在内核态和用户态下累积占用的 CPU 时间,单位是 100 纳秒。它既不是从“启动到现在”的 Wall-clock(挂钟)耗时,更不是“启动那一瞬间”的 CPU 开销。冷启动阶段的初始化开销——比如 DLL 加载、TLS 初始化、CRT 构造——这些虽然发生在用户态代码正式执行之前,但同样会被计入 `lpUserTime` 和 `lpKernelTime`。问题是,你没法把它们单独拎出来。所以,用它来度量“启动性能”,从一开始就找错了方向。

C++如何获取当前进程的启动CPU耗时 _ GetProcessTimes实战【实战】

GetProcessTimes 的正确用法:获取累计 CPU 时间

如果目标就是获取 CPU 占用时间,那它没问题。但调用前有几个前置条件必须明确: - 打开目标进程时,需要 `PROCESS_QUERY_INFORMATION` 权限。当前进程可以直接用 `GetCurrentProcess()`,省心。 - 返回的 `FILETIME` 是 64 位整数,单位 100 纳秒。直接看很懵,需要手动转成毫秒或秒。 - 即便进程已经退出了,只要句柄仍然有效,`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` 结合起来: - `lpCreationTime` 是进程被创建的精确系统时间戳(UTC 格式,精度不错)。 - 用 `GetSystemTimeAsFileTime` 拿到当前时间,两者相减,就是真实的运行时间。 **值得留意的是**:这个差值里面包含了进程所有的挂起、等待和 I/O 阻塞时间——它反映的是 Wall-clock 时长,而不是 CPU 占用时长。另外,别把 `lpCreationTime` 理解成“启动完成时间”:它仅仅是内核创建 EPROCESS 对象的时间点,比 `main()` 函数开始执行还要早。不过话说回来,对绝大多数应用场景而言,这个时间点已经足够有参考价值了。

实操中容易忽略的兼容性与精度陷阱

`GetProcessTimes` 在 Windows XP SP2 及之后的系统中都可以用,但有两处细节在实际编码里经常让人翻车: - 32 位程序在 WoW64 下调用时,`FILETIME` 本身的数值没有问题。但很多人在手动拼接 `dwLowDateTime` 和 `dwHighDateTime` 时,习惯用 `ULARGE_INTEGER` 的 `.LowPart` 字段赋值,导致高位数据丢失。这个坑很隐蔽。 - 两次调用间隔如果极端短,`lpKernelTime` 和 `lpUserTime` 可能完全没有变化。原因在于 Windows 内核只在调度周期(通常约 15ms)内更新这些计数器,它并不是实时的采样机制。 - 还有一个极罕见的场景:如果进程刚启动,还没触发任何线程调度(比如卡在 loader lock 里),那么首次调用 `GetProcessTimes` 返回的 `FILETIME` 可能是全 0。 如果真的需要在“启动性能分析”这种场景里拿到精细数据,建议直接用 ETW(Event Tracing for Windows)去捕获 `ImageLoad`、`ProcessStart`、`ThreadStart` 等事件。`GetProcessTimes` 的定位本来就是粗粒度的监控手段,用它来做性能调优,精度和维度都不太够。
本文转载于:https://www.php.cn/faq/2444765.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注