解决 oh-my-posh 加载慢


背景

使用oh-my-posh的atomic主题之后,不仅 Loading profiles 很慢,而且单行命令执行也很慢,就算只是一个回车都会有些卡顿

 

调查过程

使用 oh-my-posh 自带的 debug

oh-my-posh debug

可以查看加载过程

[TRACE] 14:47:32.446 shell_windows_nix.go:BatteryState() - 70.5656ms
[TRACE] 14:43:12.941 shell.go:CommandPath(git.exe) - 90.0136ms
[TRACE] 14:43:12.941 shell.go:HasCommand(git.exe) - 90.0136ms
[TRACE] 14:43:13.075 shell.go:CommandPath(kubectl) - 130.8147ms
[TRACE] 14:43:13.075 shell.go:HasCommand(kubectl) - 130.8147ms
[TRACE] 14:43:13.212 shell.go:RunCommand(kubectl config view --output yaml --minify) - 136.7974ms

可以看到主题需要获取git状态、k8s状态、电池状态,导致加载的很慢,这里更换一下主题。

Get-PoshThemes
# aliens

换了主题, Loading profiles 变慢,单行命令执行变快。

使用 pwsh 的Measure-Command命令

pwsh -NoProfile # 以不加载Profile的方式启动pwsh,几乎不占时间
cat $Profile
Measure-Command { some-cmd } # 测试 $Profile 中的每一行命令执行时间

oh-my-posh占用的时间是最长的。

查阅资料并测试, $Profile 中的 oh-my-posh … | Invoke-Expression 的前半部分本身就占了 86ms,只是打印出来了一个字符串

pwsh -NoProfile 直接去执行这个命令,运行时间从平均 560ms → 平均 420ms

这串代码也会生成 … | Invoke-Expression ,直接运行,直接来到 300ms

修改了 $Profile 之后,已经很满意这个加载时间了。

解决方案

$Profile 中的 oh-my-posh… 命令替换为以下脚本,缓存 oh-my-posh 脚本到 APPDATA

$config='C:\path\to\themes\aliens.omp.json'
$path= Join-Path -Path $env:APPDATA -ChildPath ('ohmyposh\' + [System.IO.Path]::GetFileNameWithoutExtension($config) + '.ps1')
if (-Not (Test-Path -Path $path)) {
    oh-my-posh init pwsh --config $config | ForEach-Object { $_ -replace "Invoke-Expression", "Out-File -FilePath $path"} | Invoke-Expression
}
& $path

参考


运行时间 427 天 | 总访问量