论 Powershell 是如何干掉我的电脑的
Pulsar2021 · · 科技·工程
总结
省流:
VSCode 背 30% 的锅
PowerShell 背 10% 的锅
oh-my-posh 背 50% 的锅
我背 10% 的锅
开端
几个月前,我在电脑上愉快的 coding。
然后发现卡的要死,遂打开 taskmgr。
一看吓一跳,硬生生有十几个 pwsh.exe 进程。
taskkill /f /im pwsh.exe 搞定。
但显然,这个东西治标不治本,因为我经常把我的 wintogo 插到机房电脑上用,而机房电脑性能好的一匹,于是这个问题被掩盖了。
发展
前两天,外培,被迫使用自己的电脑,因为我好像应该管这里的机房电脑叫爹。
于是,这个问题又出现了。
这一次,taskkill 挡不住了。
问 DeepSeek,它让我运行 Get-CimInstance Win32_Process -Filter "Name = 'pwsh.exe'" | Select-Object CommandLine。
结果:
CommandLine
-----------
"C:\Program Files\PowerShell\7\pwsh.exe" -noexit -command "try { . \"c:\Program Files\Microsoft VS Code\resources\app\out\vs\workbe…
"C:\Program Files\PowerShell\7\pwsh.exe" -noexit -command "try { . \"c:\Program Files\Microsoft VS Code\resources\app\out\vs\workbe…
"C:\Program Files\PowerShell\7\pwsh.exe" -c "git diff --no-index --no-renames --unified=0 C:\Users\Gary\AppData\Local\Temp\tmp-2176…
"C:\Program Files\PowerShell\7\pwsh.exe" -c "git diff --no-index --no-renames --unified=0 C:\Users\Gary\AppData\Local\Temp\tmp-2176…
"C:\Program Files\PowerShell\7\pwsh.exe" -c "git diff --no-index --no-renames --unified=0 C:\Users\Gary\AppData\Local\Temp\tmp-2176…
"C:\Program Files\PowerShell\7\pwsh.exe" -c "git diff --no-index --no-renames --unified=0 C:\Users\Gary\AppData\Local\Temp\tmp-2176…
"C:\Program Files\PowerShell\7\pwsh.exe" -c "git diff --no-index --no-renames --unified=0 C:\Users\Gary\AppData\Local\Temp\tmp-2176…
"C:\Program Files\PowerShell\7\pwsh.exe" -c "git diff --no-index --no-renames --unified=0 C:\Users\Gary\AppData\Local\Temp\tmp-2176…
"C:\Program Files\PowerShell\7\pwsh.exe" -c "git diff --no-index --no-renames --unified=0 C:\Users\Gary\AppData\Local\Temp\tmp-2176…
(以下省略一堆一样的)
显然可以看出,这个锅主要在于
"C:\Program Files\PowerShell\7\pwsh.exe" -c "git diff --no-index --no-renames --unified=0 C:\Users\Gary\AppData\Local\Temp\tmp-2176…
那这个命令是谁调用的呢?
高潮
VSCode 有 git 集成。
而每次卡的时机都是保存文件的时候。
而我的工作区内正好有一个 git 仓库。
合理怀疑是 git 集成的锅。
实际上是 DeepSeek 这么说的
而这个东西竟然从 pwsh 调用,而 pwsh 的配置文件中带着 oh-my-posh 的初始化,tsk 中也可见 oh-my-posh 进程,所以卡顿主要是 oh-my-posh 初始化造成的。(oh-my-posh 初始化至少占了 800ms)
结局
知道了问题,自然要对症下药。
我想了个邪招:当 pwsh -c|Command 传入的命令包含 git 时,直接跳过绝大部分非必要的初始化。
$rawArgs = [Environment]::GetCommandLineArgs()
# 检测 -c 或 -Command 参数是否存在并截取传入的命令
$commandToRun = $null
for ($i = 0; $i -lt $rawArgs.Count; $i++) {
if ($rawArgs[$i] -in '-c', '-Command' -and ($i + 1) -lt $rawArgs.Count) {
$commandToRun = $rawArgs[$i + 1]
break
}
}
# 检测 git
if ( -not ($commandToRun -and ($commandToRun -match '^(.*\\|.*/|)git(\.exe)?(\s|$)'))) {
# 初始化部分
}
Powered By DeepSeek
效果:
# 优化前
$ Measure-Command { pwsh -c "git status" }
Days : 0
Hours : 0
Minutes : 0
Seconds : 3
Milliseconds : 632
Ticks : 36329216
TotalDays : 4.20477037037037E-05
TotalHours : 0.00100914488888889
TotalMinutes : 0.0605486933333333
TotalSeconds : 3.6329216
TotalMilliseconds : 3632.9216
# 优化后
$ Measure-Command { git status }
Days : 0
Hours : 0
Minutes : 0
Seconds : 0
Milliseconds : 199
Ticks : 1994483
TotalDays : 2.30842939814815E-06
TotalHours : 5.54023055555556E-05
TotalMinutes : 0.00332413833333333
TotalSeconds : 0.1994483
TotalMilliseconds : 199.4483
$ Measure-Command { pwsh -c "git status" }
Days : 0
Hours : 0
Minutes : 0
Seconds : 1
Milliseconds : 43
Ticks : 10439697
TotalDays : 1.20829826388889E-05
TotalHours : 0.000289991583333333
TotalMinutes : 0.017399495
TotalSeconds : 1.0439697
TotalMilliseconds : 1043.9697
这样下来之后,再也没有过动不动卡半天外加 cpu、内存占用率满的问题了。
不过即使如此,用 pwsh 调用 git 还是会有大约五倍于直接执行的用时,不过至少在可接受范围内了。
教训:最好不要在任何 Shell 的初始化阶段干耗时的事情,尤其是在要求高效率的时候。