ARTICLE · 1286464
电脑越用越卡? 可能是装的软件拖累了系统,我的windows卡的排查记录分享
我的工作电脑有一个怪毛病:刚开机的时候很流畅,用上几个小时就开始卡,鼠标拖着走,打字慢半拍,点什么都要顿一下,重启以后又好了。
打开任务管理器看,CPU、内存、磁盘都不高。我把浏览器、Cursor 这些吃内存的程序全关了,还是卡。
前前后后查了一周,最后发现元凶是两个后台程序:VS Code 和 Cursor 的自动更新安装程序,以及 WPS 的后台进程。它们有一个共同点,就是窗口挂在那里,却不处理任何消息。
这篇文章记录整个排查过程。我觉得值得写下来,因为这类问题用常规办法很难发现,而用 VS Code 或 Cursor、平时又不怎么关编辑器的程序员,很可能也会碰到。
一、先把“卡”量出来
“有点卡”是一种感觉,没法比较,也没法验证。所以第一步,是找一个能反复测量的数字。
我选的是低级鼠标钩子的延迟。所谓低级鼠标钩子(low-level mouse hook,代码里叫 WH_MOUSE_LL),就是 Windows 提供的一种机制,让程序可以监听全局的鼠标动作。划词翻译、截图工具、输入法、安全软件都喜欢用它。
鼠标每动一下,系统都要把这个动作依次交给每个钩子,等它们都返回了,光标才会真正移动。链条上任何一环变慢,你都会觉得鼠标在拖。
测量的办法不复杂。我写了一个 PowerShell 脚本,自己装一个低级鼠标钩子,然后模拟 150 次 1 像素的鼠标移动。因为我的钩子是最后装的,所以最先被调用;它再把动作传给下一个钩子(CallNextHookEx),给这一步计时,就是链条上其他所有钩子加起来的耗时。
请看电脑正卡的时候(开机约 24 小时)测到的结果。

上面是连续测 3 轮的结果,单位是毫秒。P90 的意思是 90% 的鼠标动作都在这个时间以内处理完。刚开机时这个数字是 1 毫秒左右,现在是 150 毫秒,最慢的一次超过了 2 秒。屏幕刷新一帧是 16.7 毫秒,150 毫秒就是差不多九帧,难怪鼠标会拖。
有了这个数字,以后每改一个地方,几十秒就能知道有没有用。我还让一个后台脚本每 5 分钟测一次,顺便记下内存、句柄、内核内存池这些指标,连续跑了 14 个小时。后来真正的线索,就是从这份记录里找到的。
二、走过的弯路
在找到真正的原因之前,我怀疑过好几样东西,每一个当时看起来都很合理。
(1)鼠标没电。这是最常见的原因,但打字也卡,重启又好,显然不是鼠标的事。
(2)显示器或显卡。我接了两块屏幕,分别连在不同的显卡上,很像是切换屏幕时出问题。可是拔掉一块只用单屏,照样卡。
(3)内存或 CPU。这是大家的第一反应,但卡的时候资源占用一直不高,关掉大程序也没用。
(4)某个装了鼠标钩子的程序。有一次我把豆包桌面版、微信、微软电脑管家、WPS 云服务一起关掉,延迟当场从 70 毫秒降到 0.3 毫秒。我以为元凶就在这四个里,当天先把嫌疑最大的豆包停掉观察,结果第二天照样卡。
后来翻记录才发现,关程序的同一时刻,VS Code 正好重启了一次。真正起作用的,很可能是这次重启,再加上那四个里碰巧夹着的 WPS 云服务。
一次关掉一堆程序以后变好了,不能当作证据,得一个一个关,每关一个测一次。这个道理谁都懂,可是电脑卡得心烦的时候,很容易忘掉。
三、内核里的积压
记录里的大部分指标都很平稳,只有一项和鼠标延迟几乎同步变化,它叫 Ussm。
这里要先说一下内核内存池。Windows 内核里的各个组件申请内存时,都会贴一个 4 个字符的标签(pool tag),说明这块内存是谁的、干什么用的。Ussm 属于 win32k,也就是 Windows 负责窗口和输入的那一块。按照它的命名习惯,这个标签对应的是「发给别的线程、还没被处理的消息」。
正常情况下,消息发出去很快就会被处理掉,这一项应该接近 0。可我的电脑开机 14 小时以后,它涨到了 151MB。

图1:后台脚本每 5 分钟采样一次,2026年10月13日 09:34 至 23:34,共 164 次
上图是那一天的记录,上半部分是鼠标延迟,下半部分是 Ussm。可以看到,两条线是一起走的:开机 9 小时以后,积压每小时增加约 24MB,延迟也跟着从单位数毫秒涨到 100 毫秒。中间 8 小时那里,两条线一起掉下来,就是上一节说的那次“关掉四个程序、VS Code 又刚好重启”。
这就是突破口。积压不会凭空出现,只有某个窗口一直不处理别人发来的消息,消息才会越堆越多。下一步,就是把这个窗口找出来。
四、找到卡住的窗口
任务管理器会把没响应的程序标成「未响应」,但它只看你能看到的主窗口。后台程序的窗口大多是隐藏的,卡死了也没人知道。
所以我又写了一个脚本,把系统里所有的窗口都枚举一遍,包括专门用来收消息、从不显示的那种。对每一个窗口,先用 IsHungAppWindow 问系统它是不是已经被判定为无响应,再给它发一条什么也不干的空消息(WM_NULL),看 300 毫秒内有没有回应。
第二天上午,电脑开机已经 24 小时,积压涨到了 221MB,连打字都卡。扫描结果里有两行特别显眼(哈希值有删节)。

上面两个进程,窗口都被系统判为无响应(Hung 为 True),发过去的消息也没有回应(Ok 为 False)。
它们都是安装程序。哈希值开头的那个是 VS Code 的后台更新,凌晨 1:06 启动。另一个名字里带着 3.24.18,这不是 VS Code 的版本号,而是 Cursor 的。Cursor 是从 VS Code 改出来的,连更新程序的名字都没改,它早上 6:00 启动。
结束这两个进程,前后各看一次积压。

上面输出中,0/221 的意思是非分页池 0MB、分页池 221MB。4 秒钟之后,221MB 变成了 1MB。
再测一次鼠标延迟。

P90 从 150 毫秒降到了 0.4 毫秒,最慢的一次也只有 12 毫秒,和刚开机时一样。这一步只结束了这两个进程,其他什么都没动。
五、问题是怎么发生的
把前面的事实串起来,过程是这样的。
VS Code 和 Cursor 在 Windows 上会在后台自动下载更新,下载完就启动安装程序。可编辑器正开着,它的文件被占用,没法直接替换,安装程序只好等编辑器退出。如果你像我一样,编辑器开着就不关,它就一直等下去。

图2:从编辑器不关到整机变卡的过程
上图里,实线连着的几步都有直接证据:安装程序的启动时间、它的窗口被判为无响应、结束它以后积压马上消失。积压和变慢同时出现、同时消失,这也是测到的。
但积压为什么会拖慢整台电脑,我没有在 Windows 内部验证过,下面只是我的推测。Windows 的窗口消息由一把全局锁保护,跨线程发送的消息也挂在全局的结构上,积压到几百 MB 以后,很多要经过它的操作都会变慢;而低级鼠标钩子和键盘钩子,恰好也要走跨线程消息这条路。这样就能解释为什么 CPU 很空,光标却在卡。
我觉得,安装程序等编辑器退出没有错,错的是它等的方式。等的时候应该继续处理消息,或者干脆先退出、下次启动再装,而不是把一个不响应的窗口挂在那里好几天。
六、第二个元凶:WPS
把 VS Code 和 Cursor 改成手动更新以后,我以为事情就结束了。结果当天下午,又感觉到一点轻微的卡。
重新开机才 6 小时,Ussm 已经涨到 55MB,而这次没有任何安装程序。用同样的办法扫描,无响应线程最多的是 WPS 的云服务 wpscloudsvr.exe,有 6 个线程卡着。结束它以后,积压从 55MB 降到 1MB,P90 从约 12 毫秒降到 0.6 毫秒。
麻烦的是,WPS 的这些后台进程很难关干净。
(1)WPS 设置里的「云同步」本来就是关着的,wpscloudsvr 照样在跑。看它的启动参数,里面有 silentautologin,它管的是账号的静默登录,跟同不同步没关系。
(2)刚打开 WPS,它的各个进程里就有 18 个「建了窗口却从不处理消息」的线程。这是程序本身的写法,改设置没有用。
(3)关掉 WPS 的窗口以后,后台还剩 7 个进程。
(4)就算不开 WPS,它也会自己起来。资源管理器左侧有一个「WPS网盘」入口,只要打开任意一个文件夹,它就把 wpscloudsvr 拉起来(启动参数是 start_from=qingnse)。另外还有一个每 30 分钟运行一次的计划任务,和两个登录时运行的任务。
我先去掉了那个网盘入口,禁用了这几个计划任务,但只要还在用 WPS,这些后台进程就还会在。最后我干脆卸载了 WPS,之后又用了好多天,电脑再也没卡过。
顺便说一句,第三节图里 13 日晚上那一段积压,发生的时候 VS Code 和 Cursor 的安装程序都还没启动,当时我也没抓到是谁卡着。现在回头看,WPS 的嫌疑最大。
七、怎么避免,怎么自己查
如果你用 VS Code 或 Cursor,又习惯开着编辑器不关,最简单的办法是关掉后台自动更新。在用户设置文件 settings.json 里加一行。
{ "update.mode": "manual" }
上面的设置表示不再自动下载和安装更新,什么时候想升级,自己点「检查更新」。VS Code 的设置文件在
%APPDATA%\Code\User\settings.json,Cursor 的在
%APPDATA%\Cursor\User\settings.json,改完要重启编辑器才生效。
注意,关掉编辑器窗口,不一定代表它真的退出了。我这次就遇到过,窗口关了,还有几个 Code.exe 挂在后台,更新程序就一直等。
如果你的电脑也是“越用越卡、重启就好、资源占用不高”,可以按下面的顺序查。
(1)打开任务管理器的「详细信息」,找有没有 CodeSetup 开头的进程,有的话直接结束。这一步最省事。
(2)看 Ussm 有多大。微软的 WDK 里有一个工具叫 PoolMon,运行 poolmon -b 会把所有标签按占用字节排序,找到 Ussm 那一行就行。正常应该接近 0,几十 MB 以上就说明有窗口卡着消息。
(3)找出卡着的窗口。用 EnumWindows 和 FindWindowEx(HWND_MESSAGE, ...) 枚举所有顶层窗口和消息窗口,对每一个调用 IsHungAppWindow,再按进程归类。
(4)一个一个结束嫌疑进程,每结束一个就重新看一次 Ussm。积压一下子掉到接近 0 的那个,就是元凶。
(5)顺着进程的启动参数和父进程,找到它是被谁拉起来的,重点看计划任务、注册表里的启动项和资源管理器扩展。
八、一点感想
这次排查让我意识到,只看 CPU 和内存来判断电脑健不健康,是不够的。任务管理器显示的都是“用了多少”,可这次的问题是“有人不干活”,一个不处理消息的窗口几乎不占资源,却能让整台电脑的输入都慢下来。
现在的桌面软件,几乎都有自己的后台进程、自动更新和开机任务。每一个单独看都不过分,可它们都默认自己可以一直挂着。我估计像这样的问题不会少,只是大多数人重启一下就算了,不会去追究。
这个问题我已经报给了 VS Code 团队(#341445,英文)。我搜过 VS Code 的 GitHub 和 Cursor 论坛,有不少人报告过更新程序卡住、更新不上,比如 Cursor 论坛的这个帖子(英文),也有人报告过整机鼠标键盘时不时没反应(#154879,英文),但没找到有人把这两件事联系起来。















































































