那些吃CPU的大户

作者通过检查任务管理器,发现IDLE进程和多个应用消耗大量CPU时间。深入分析系统进程,发现GPU管理和内存相关线程是主要消耗者。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    最近沉浸在代码的世界里,处于两耳不闻窗外事的状态。今晚偶有闲暇,看了一眼任务管理器,IDLE进程的时间居然有800多小时,还有多个进程的CPU净时间达到小时级别。

    如下图所示,IDLE进程的CPU净时间为832个小时18分15秒。这说明我很长时间没有重启这台电脑了。除了IDLE进程,CPU净时间达到小时级别的还有8位,它们是本文的主角。

640?wx_fmt=png

    8个达到小时级别的进程分别是:

  • 系统进程,排名第1位,累计用CPU时间接近17个小时,这个很不正常,稍后深入探究

  • dwm,桌面窗口管理器,排名第2位,也有些意外

  • ism2,英特尔公司的软件更新管理工具,排名第3位,不干什么正事的应用,还花这么多时间,多半是有劣质代码乱跑,不过算了吧,不多说了

  • msmpeng.exe,Windows自带的安全引擎,一般来说,安全软件是吃CPU的大户,一般它是要排在前三的,现在落到第4了,真的算很好了,要表扬一下

  • svchost.exe,后台服务的宿主进程,根据进程号查一下,这个进程里的服务是superfetch,提高性能用的,念其用心良苦,花些时间也不责怪它了

  • baidunetdisk.exe,百度网盘的客户端,也就是以前的百度云管家,老雷曾经批判过的。不知道是不是与老雷的文章有关,文章发表后,这个工具洗心革面,不仅改了以前的问题,而且改了名字。安静一年多了,最近一段时间感觉又有些激进,经常占很多CPU和I/O。可能是团队里来新员工了吧?

  • 接下来两位是explorer和powerpoint,没啥好说的了,两个人的活确实比较累


为什么达到小时级别值得关注呢?因为今天的CPU太快了,真可谓风驰电掣,一秒钟可以执行几G条指令。不信你看,任务管理器里面排在后面的很多程序用的CPU净时间都是0小时0分0秒,这些都是绿色标兵。

640?wx_fmt=png

    值得表扬的是旺旺客户端(加亮的那个),老雷今年年初曾经批评过它,开发工程师联系我,说会改正问题,看来改进的不错。


    回过头来再说系统进程吧,它是内核的宿主。内核相当于软件世界的ZF,按说它应该比较轻,不花什么资源。但是现在它却占了最多的CPU时间(如此说话时,不包括IDLE进程)。

    当内核被普通线程调用时,它所占的时间是记录在调用线程上的。因此,    系统进程占的时间都是它自己的系统线程运行时花费的。

    观察任务管理器,系统进程的线程数多达190个。那么,是哪个系统线程花的时间比较多呢?要回答这个问题,没有专业工具不行了。


    唤出WinDBG,开始本地内核调试。“啊?老雷,你的机器总启用着内核调试啊?” 

    “是的!” 

    执行!process 4列出系统进程的所有线程。WinDBG一边列线程,一边加载符号,花了很久,终于搞定。

    然后搜索“KernelTime                0n” (n为1-9),于是发现一个使用4小时多的线程,有图有真相,且看:    

640?wx_fmt=png

UserTime                  00:00:00.000

KernelTime                04:24:43.437

    这是干什么的线程呢?

    从栈回溯来看,线程的主函数是dxgmms2!VidMmWorkerThreadProc,其中,dxgmms2是模块名,搜索互联网,可以找到很多与这个模块有关的蓝屏崩溃。它还有个同门兄弟,叫dxgmms1,也是一样,有很多崩溃记录。

    那么这兄弟两个是谁家的呢?是微软家的。

    做什么用的呢?是管理GPU的。再具体一点,它们肩负着两个与GPU相关的重要任务:

    - 显存管理,简称VidMM

    - GPU调度,简称VidSchi

    从上面线程的工作函数名来看,VidMmWorkerThreadProc,它是属于VidMM的。

    继续搜索用时超过2小时的线程,还有如下一个:

640?wx_fmt=png

    看它的工作函数VidSchiWorkerThread,居然就是dxgmms中的调度器线程:

    dxgmms2!VidSchiRun_PriorityTable

    dxgmms2!VidSchiWorkerThread

    继续搜索,还有一个超过2小时的线程,是igfxdcd,它是英特尔的GPU调试辅助驱动,用于调试OpenCL程序。它的设计明显存在缺欠,不管是否在调试,都有一个系统线程在跑,真是不应该。

640?wx_fmt=png

    继续搜索超过1小时的系统线程,有两个,一个是KeBalanceSetManager,是NT内核自己的,用来修剪进程工作集的。

640?wx_fmt=png

    另一个是ZeroPageThread,是用来准备清零内存页的,在内核启动时,是这个线程发起关键的执行体初始化动作,内核启动后,它退居二线,专门负责把内存页清0,当驱动程序需要已经清0的内存页时,满足需要。

640?wx_fmt=png

    综上,超过小时级别的系统线程有5个,三个是GPU相关的,另外两个是普通内存相关的。它们加起来一共消耗了10个小时多的CPU净时间,很是惊人。



***********************************************************

正心诚意,格物致知,以人文情怀审视软件,以软件技术改变人生。

欢迎关注格友公众号

640?wx_fmt=jpeg


### 如何释放 CPU 资源 在操作系统的上下文中,CPU 是一种有限的计算资源,其管理依赖于调度器来决定哪些线程或进程可以占用 CPU 时间片。为了实现高效的多任务处理和资源共享,操作系统提供了多种机制让线程主动或被动地释放 CPU。 #### 主动释放 CPU 的方法 Java 中可以通过调用 `Thread.sleep(long millis)` 方法使当前线程暂停指定的时间,在这段时间内该线程不会消耗任何 CPU 周期[^2]。此期间,线程会进入阻塞状态并将时间片交还给操作系统用于其他就绪线程的任务执行。除了睡眠外,还可以通过以下方式主动放弃 CPU: - **`yield()`**: Java 提供了一个静态方法 `Thread.yield()`, 它建议当前正在运行的线程暂时停止以便允许具有相同优先级的其他线程获得执行机会。需要注意的是,这只是一个提示而非强制行为,具体效果取决于 JVM 实现以及底层 OS 的调度策略。 - **等待条件变量 (Condition Variable)**: 当某个特定事件未发生前,可以让线程处于等待状态直到被通知唤醒为止。这种情况下也会自动释放关联锁并退出临界区从而减少不必要的轮询开销。 #### 被动释放 CPU 的场景 即使没有显式的指令去中断某一线程的工作流,只要满足一定条件下它仍然可能被迫离开处理器核心进而腾出空间给别的候选者使用: - 如果存在更高优先级的新请求到来,则低优先生命周期内的活动会被打断; - I/O 操作完成之前通常都会经历一段挂起阶段——在此过程中同样不占据实际运算能力; - 死循环检测机制也可能介入终止失控的行为模式以保护整体稳定性; 对于监控高负载环境下的单个耗能大户而言,借助工具如 top 命令加上参数 `-Hp pid`(这里的pid代表目标进程id),能够直观展示内部各个子单元的实际表现数据,并据此定位瓶颈所在位置进一步优化性能配置或者调整算法逻辑达到更好的平衡点[^3]。 ```bash top -Hp <your_process_id> ``` 上述命令可以帮助识别哪个具体的线程占用了最多的 CPU 时间,一旦发现问题就可以针对性采取措施降低它的活跃度或是重构相关部分代码提高效率。 ### 结论 综上所述,无论是编程语言层面还是系统运维角度都有相应的手段用来管理和控制 cpu 使用状况,合理运用这些技术不仅可以提升用户体验还能延长硬件寿命降低成本支出。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值