linux下用clock_gettime(clock_thread_cputime_id, ...)可精确获取当前线程cpu时间,需两次调用相减得耗时;windows下用getthreadtimes(),须用openthread获取真实句柄,filetime需转纳秒。

Linux下用clock_gettime(CLOCK_THREAD_CPUTIME_ID, ...)最直接
这是POSIX标准支持的方式,能精确获取当前线程已使用的CPU时间(不包括睡眠、阻塞等挂起时间),且开销极小。注意它返回的是纳秒级绝对时间戳,需两次调用相减才能得到耗时。
-
CLOCK_THREAD_CPUTIME_ID在glibc 2.17+和内核2.6.12+上可用,老系统可能报EINVAL - 必须链接
-lrt(尤其在某些静态链接或嵌入式环境中) - 示例:
struct timespec ts;<br>if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts) == 0) {<br> uint64_t nanos = ts.tv_sec * 1000000000ULL + ts.tv_nsec;<br>}
Windows上用GetThreadTimes()但要注意单位转换
它返回的是100纳秒为单位的FILETIME结构,需转成毫秒或纳秒才方便计算。关键点是:它返回的是内核态+用户态总时间,且必须传入当前线程句柄(不能用GetCurrentThread()返回的伪句柄直接调用,需先DuplicateHandle或用OpenThread)。
- 常见错误:直接对
GetCurrentThread()返回值调用GetThreadTimes(),结果总是0或失败 - 正确做法是用
GetCurrentThreadId()配合OpenThread(THREAD_QUERY_INFORMATION, ...) - FILETIME转纳秒:用
((int64_t)ft.dwHighDateTime 再乘100
跨平台封装时别依赖std::chrono::high_resolution_clock
这个时钟在多数实现中是系统单调时钟(wall-clock),不是CPU时间。即使文档说“高精度”,它也不反映线程实际占用CPU的时长——比如线程sleep 1秒,high_resolution_clock会走1秒,但CPU时间几乎为0。
- 误用后果:在性能分析、超时控制、资源配额等场景得出完全错误结论
- 若真要跨平台,建议用条件编译封装
clock_gettime(Linux/macOS)和GetThreadTimes(Windows),避免抽象层掩盖语义差异
注意线程ID与执行上下文的绑定关系
获取到的时间值只对调用时刻有效的线程实例有意义。如果线程已退出,或你拿到的是其他线程的句柄/ID,clock_gettime会失败(Linux返回-1并设errno=ESRCH),GetThreadTimes会返回FALSE且GetLastError()为ERROR_INVALID_HANDLE。
- 不要缓存线程时间戳用于后续比较,除非你明确知道该线程仍在运行且未被复用(如线程池中线程可能被反复使用)
- 在多线程调试中,容易把主线程时间误认为工作线程时间——务必确认
pthread_self()或std::this_thread::get_id()与目标一致
真正难的不是调哪个函数,而是想清楚你要测的是“这段代码实际占了多少CPU”,还是“从开始到结束经过了多久”。这两个量在现代操作系统里差得远。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











