Windows 沙箱内取系统指标 / 回答「为什么卡」
用户问「怎么这么卡?东西太多了吗?」时,不要凭感觉答,也不要顺着用户猜。
先取实测数据,再判读,最后给出区分「机器」与「会话」的结论。
★★ 第一坑:本环境 PowerShell 工具可能返回空
实测(2026-09-16):PowerShell 工具执行 Get-Process、Get-CimInstance Win32_OperatingSystem、
Get-CimInstance Win32_LogicalDisk —— stdout 完全为空、stderr 也为空、无报错。
同一时刻 Bash 里的 tasklist 工作正常。
⇒ 不要因为 PowerShell 没输出就断定「查不到」,立刻换 Bash 侧命令或 Python ctypes。
另外 wmic 在新版 Win11 上可能已被移除(实测 wmic ComputerSystem get TotalPhysicalMemory 返回空、exit 1)。
三条可靠的取数路径(都实测可用)
1. 内存总量 / 可用量 / 负载 — Python ctypes
import ctypes
class MS(ctypes.Structure):
_fields_=[('dwLength',ctypes.c_ulong),('dwMemoryLoad',ctypes.c_ulong),
('ullTotalPhys',ctypes.c_ulonglong),('ullAvailPhys',ctypes.c_ulonglong),
('ullTotalPageFile',ctypes.c_ulonglong),('ullAvailPageFile',ctypes.c_ulonglong),
('ullTotalVirtual',ctypes.c_ulonglong),('ullAvailVirtual',ctypes.c_ulonglong),
('ullAvailExtendedVirtual',ctypes.c_ulonglong)]
m=MS(); m.dwLength=ctypes.sizeof(MS)
ctypes.windll.kernel32.GlobalMemoryStatusEx(ctypes.byref(m))
G=1024**3
print('总 %.1f GB 可用 %.1f GB 负载 %d%%'%(m.ullTotalPhys/G,m.ullAvailPhys/G,m.dwMemoryLoad))
2. CPU 占用率 — GetSystemTimes 两次采样
import ctypes, time
from ctypes import wintypes
k=ctypes.windll.kernel32
class FT(ctypes.Structure): _fields_=[('lo',wintypes.DWORD),('hi',wintypes.DWORD)]
def snap():
i=FT(); ke=FT(); u=FT()
k.GetSystemTimes(ctypes.byref(i),ctypes.byref(ke),ctypes.byref(u))
return (i.hi<<32)|i.lo,(ke.hi<<32)|ke.lo,(u.hi<<32)|u.lo
a=snap(); time.sleep(2); b=snap()
idle=b[0]-a[0]; tot=(b[1]-a[1])+(b[2]-a[2])
print('CPU %.1f%%'%(100*(1-idle/tot)))
⚠️ 采样窗口别短于 1 秒,否则噪声极大。os.cpu_count() 拿逻辑核数。
3. 进程按名聚合 + 无响应窗口 — Bash 侧 tasklist
# 单进程 top(第 5 列是内存,形如 "1,835,728 K")
MSYS_NO_PATHCONV=1 tasklist /FO CSV /NH | awk -F'","' '{gsub(/"/,"",$1); gsub(/[^0-9]/,"",$5); print $5"\t"$1"\t"$2}' | sort -rn | head -20
# 无响应窗口("卡死"的进程一目了然)
MSYS_NO_PATHCONV=1 tasklist /V /FI "STATUS eq NOT RESPONDING" /FO CSV /NH
# 磁盘
df -h | grep -E "^[A-Z]:"
按名聚合(Electron 应用动辄 16+ 进程,必须聚合才看得懂)用 Python:
tasklist /FO CSV /NH → stdout.decode('gbk','ignore')(GBK,不是 utf-8)
→ 按第 1 列 group、第 5 列去非数字后求和。
判读口径(先分开「机器」和「会话」)
| 指标 | 健康线 | 超线含义 |
|---|---|---|
| CPU 占用 | < 30% | 真忙;查 qgis/ArcMap/杀毒扫描 |
| 内存可用 | > 25% 总量 | 已开始压缩(看 Memory Compression 进程,> 1 GB 说明吃紧) |
| 磁盘可用 | > 10% | 系统盘 < 10% 会明显拖慢 |
| 无响应窗口 | 0 | 逐个看是谁,别一锅端杀 |
★ 关键判断:如果 CPU 低 + 内存有余 + 磁盘有余,但用户仍觉得卡 ——
几乎一定是当前会话上下文太长,不是机器问题。对用户要明确这样说,别让他去换电脑/清 C 盘。
会话侧怎么量化(拿去给用户看证据)
- 本轮工具调用次数、读进上下文的图片张数与体积(高分渲染图是最大元凶 ——
一次 1600 dpi 的fitz渲染 +Read就是几百 KB~几 MB 进历史) - 磁盘侧找证据:
ls -la <工作目录>/*.png | awk求和
常见"看着可疑但通常无罪"的住户
- Electron 应用:WorkBuddy 17 进程 / Trae CN 16 进程 —— 多进程是架构设计,不是泄漏
- 百度网盘(
BaiduNetdiskUnite+baidunetdiskhost)12 进程近 1 GB,不用时应退出 svchost.exe84 个 —— 正常,Windows 服务宿主MsMpEng.exe(Defender)占 CPU 时是真在扫,别杀Memory Compression> 1.5 GB:内存已吃紧的信号(但在这台 32 GB 机上属正常波动)
给用户的建议话术(按性价比排序)
- 开新会话(最有效,且零风险)——把上下文清空
- 关掉上次批量任务留下的 WPS/Office 残留进程(导 PDF 后常见 5+ 个残留)
- 退出不用的常驻程序(网盘、QGIS、另一个 IDE)
- 不建议在没证据时动「清理 C 盘」「重装系统」「加内存」这类方案
红线
- 杀进程前先报告"是谁、多大、可能有什么未保存内容",确认后再动手。
- 用户自己的 IDE / WPS / QGIS 里可能有未保存文档,不要自作主张杀。
- 会话工作目录里的一堆
_*.py/*.log只是杂,不构成性能问题,别拿它当"卡"的原因。