系统资源 4 维度诊断
核心原则(最重要,先看这条)
"反复读硬盘" ≠ 有程序在主动狂读。先查内存占用率。
| 内存占用率 | 磁盘狂读的真正原因 |
|---|---|
| ≥ 90% | Windows 疯狂分页到 pagefile.sys → 磁盘狂读。不是程序 bug,是内存压力副作用 |
| 50-90% | 可能是分页 + 真实 I/O 混合,需进一步采样 |
| < 50% | 磁盘 I/O 低却仍报"读盘" → 才需要按进程查真实 I/O |
2026-09-08 实战验证:用户报"反复读硬盘",08:43 采样发现内存 100% 满、WorkBuddy 读 3,192 KB/s;清理 GTJANetSignCNG(1.17GB) + Spooler + 8 个 OEM 自启项后,09:46 内存降到 24.5%,磁盘读取峰值降到 6.6 KB/s(降 480 倍)。全程没有"杀掉狂读的程序",问题自动消失。
量化分页压力:
Get-Counter '\Memory\Page Reads/sec' # > 100 说明在疯狂分页
Get-Counter '\Memory\Pages Input/sec'
触发词
反复读硬盘 / 硬盘灯狂闪 / 内存占用高 / 卡顿 / 风扇狂转 / 网速慢 / 哪个程序偷跑流量 / CPU 异常 / 系统资源检测 / 电脑变慢
诊断流程(4 维度,按顺序)
Step 0:系统概览 + 判定内存压力(必做,5 秒)
$mem = Get-CimInstance Win32_OperatingSystem
$bootTime = $mem.LastBootUpTime
$uptimeMin = [math]::Round((New-TimeSpan -Start $bootTime -End (Get-Date)).TotalMinutes, 1)
$procs = Get-Process
# 输出:上次启动时间 / 已运行分钟 / 进程总数 / 工作集总计 / 物理内存已用%
uptimeMin < 30→ 刚重启,需等系统稳定(启动项加载完)再采样,否则数据偏乐观- 物理内存已用 ≥ 90% → 直接跳到"内存 Top 15"找元凶,磁盘问题多半是它的副作用
Step 1:内存 Top 15(单采样即可)
Get-Process | Sort-Object WorkingSet64 -Descending | Select-Object -First 15 |
Select-Object ProcessName, Id,
@{N='工作集MB';E={[math]::Round($_.WorkingSet64/1MB,1)}},
@{N='占比%';E={[math]::Round($_.WorkingSet64/(Get-Process|Measure-Object WorkingSet64 -Sum).Sum*100,1)}}
注意同名多实例要合并看(如 WorkBuddy 6 进程合计 1.65GB,单看每个才 200-600MB 会误判)。
Step 2:磁盘 I/O + CPU(双采样 5 秒,判断"持续" vs "间歇")
$counters = @('\Process(*)\IO Read Bytes/sec','\Process(*)\IO Write Bytes/sec','\Process(*)\% Processor Time')
$s1 = Get-Counter -Counter $counters -ErrorAction SilentlyContinue
Start-Sleep -Seconds 5
$s2 = Get-Counter -Counter $counters -ErrorAction SilentlyContinue
# 对同一 InstanceName 取两次值,都高 = 🔴 持续;一高一低 = 🟡 间歇
必须用双采样:单采样无法区分"持续狂读"和"恰好抓到一次瞬时峰值"。判据:
Persistent = if ($r1 -gt 50KB -and $r2 -gt 50KB) { '🔴 持续' }
elseif ($r1 -gt 50KB -or $r2 -gt 50KB) { '🟡 间歇' } else { '' }
Step 3:网络(双采样 3 秒 + 连接统计)
# 接口速率 + 带宽利用率
Get-Counter @('\Network Interface(*)\Bytes Received/sec','\Network Interface(*)\Bytes Sent/sec','\Network Interface(*)\Current Bandwidth')
# 按进程统计连接数
Get-NetTCPConnection -State Established | Group-Object OwningProcess | Sort-Object Count -Descending
# 外联目标(排查异常外联)
Get-NetTCPConnection -State Established | Where-Object { $_.RemoteAddress -notmatch '^(127\.|::1|0\.0\.0\.0)' } |
Group-Object RemoteAddress | Sort-Object Count -Descending
带宽利用率 = (Recv + Send) / CurrentBandwidth * 100。
Step 4:出结论(对标阈值表,见下)
Step 5:历史/睡眠窗口重建(用户问"某个过去时段是否异常"时)
Windows 默认不保留逐进程历史磁盘 I/O(无内置环形缓冲)。无法回溯"11:30 谁在读盘"。用以下方法重建:
- 先确认系统到底有没有醒着——读睡眠/唤醒事件:
Get-WinEvent -FilterHashtable @{LogName='System'; ProviderName='Microsoft-Windows-Kernel-Power'; Id=@(42,107,131); StartTime=(Get-Date).AddHours(-30)} |
Sort-Object TimeCreated | ForEach-Object { "$($_.TimeCreated) [$($_.Id)] $($_.Message.Split([Environment]::NewLine)[0])" }
Get-WinEvent -FilterHashtable @{LogName='System'; ProviderName='Microsoft-Windows-Power-Troubleshooter'; Id=1} -ErrorAction SilentlyContinue
- 关键事件:Id=42 进入睡眠 / Id=107 从睡眠恢复 / Id=131 固件 S3 计时(ResumeCount 标记真正唤醒)/ Power-Troubleshooter Id=1 "从低功耗恢复"。
- 核心判定:若目标时段大部分落在 S3 睡眠内 → 该时段零磁盘 I/O,所谓"反复读写"不可能发生;只有"睡前若干分钟"和"唤醒后几分钟"两个活跃子窗口可能有 I/O。
-
睡眠保活 = 进程集不变:S3 睡眠不杀进程、不重启。因此当前进程列表 ≈ 该时段驻留进程集(除非时段内有重启,用
Win32_OperatingSystem.LastBootUpTime验证)。"哪些程序在运行"→ 直接给当前进程快照即可。 -
唤醒后一次性任务会短暂狂读,常见且正常:
MsMpEng(Defender 唤醒扫描)、SearchIndexer(重建索引)、Windows Update。查 Defender 扫描事件确认:
Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-Windows Defender/Operational'; Id=@(1006,1007,1015)} -ErrorAction SilentlyContinue
- 实时快照兜底:在活跃子窗口或唤醒后尽快跑 Step 0–2。若唤醒后 10+ 分钟磁盘已空闲(仅
dwm3-5KB/s)、内存 <50%、Page Reads/sec <10 → 无异常。所谓"反复读写"多半是昨日已修复的内存分页副作用或唤醒瞬间的正常索引 burst。
2026-09-09 实战:用户问"昨天11:30→今早唤醒是否反复读盘"。证据:boot 09-08 11:18、sleep 09-08 11:47、wake 09-09 08:16(Kernel-Power Id=131 ResumeCount=1)。即 20.5h/20.8h 处于 S3 睡眠 → 零 I/O。唤醒 12 分钟后快照:内存 31.9%、Page Reads/sec=3、仅 dwm 读 3.4KB/s、无任何进程写盘 >1KB/s。结论:该时段无异常反复读写,机器绝大部分时间在睡觉。
阈值判读表
| 维度 | 🟢 健康 | 🟡 关注 | 🔴 异常 |
|---|---|---|---|
| 磁盘读(单进程) | < 100 KB/s | 100 KB/s - 1 MB/s | > 1 MB/s 且"持续" |
| 磁盘写(单进程) | < 100 KB/s | 100 KB/s - 1 MB/s | > 1 MB/s 且"持续" |
| 物理内存已用 | < 70% | 70-90% | ≥ 90% |
| CPU(单进程,非内核) | < 5% | 5-20% | > 20% 持续 |
| 网络利用率 | < 10% | 10-50% | > 50% |
| Established 连接总数 | < 50 | 50-200 | > 200(疑似异常外联) |
常见"伪异常"清单(不要误报)
| 进程 | 正常表现 | 说明 |
|---|---|---|
System |
CPU 10-20% | 内核态(驱动 + 中断),正常 |
dwm |
CPU 5-10%,读 3-5 KB/s | 桌面窗口管理器(桌面合成 + 动画) |
MsMpEng |
内存 100-400 MB,CPU < 2% | Windows Defender 实时防护 |
SearchApp / SearchIndexer |
内存 150-200 MB,间歇读盘 | Windows 搜索索引,建索引时会短暂狂读,属正常 |
taskmgr |
CPU 1-3% | 任务管理器自身采样开销 |
svchost (多个) |
每个 20-120 MB | 系统服务宿主,看 -a 参数才知道是哪个服务 |
Registry |
内存 80-100 MB | 注册表,正常 |
| 同名进程多实例 | 单个不大但合计大 | 如 WorkBuddy / Chrome / Edge,必须合并看 |
输出规范(用户偏好)
按用户的偏好,诊断结果用结构化表格 + 结论先行:
1. 结论先行:一句话 + 状态表(4 维度各一个 ✅/🟡/🔴)
2. 前后对比表(如果有历史基线):指标 / 之前 / 现在 / 变化
3. 4 维度明细:每维度 Top N 表格
4. 判定:是否需要干预 + 唯一可优化项
5. 下一步选项(3 个,A/B/C 形式)
相关脚本
scripts/diagnose_resources.ps1 —— 一键跑完 4 维度(含双采样 + 阈值判定 + 彩色输出),已内置本文所有判据。
与其他 skill 的边界
- 本 skill 回答"现在谁在占资源"(实时诊断)
startup-audit回答"开机时谁会被拉起来"(启动项治理)- 两者常配合:本 skill 发现可疑进程 → 用
startup-audit查它是不是自启项 → 决定禁用还是结束进程 edge-troubleshooter是 Edge 专项,本 skill 是全局资源视角