解决zsh启动速度慢的优化方法

解决zsh启动速度慢的优化方法

前排插入blog


1. 为啥要解决这个问题?

我的zsh打开实在是太太太太卡了,卡哭...~~严重影响了我的工作效率~~

Q:那么为啥会卡呢? A:好问题!因为.zshrc 里有太多太多的各类语言、启动逻辑和环境变量的配置,所以卡的一批。

2. 一个优化的小tip,针对iterm2

进入 iTerm2 的偏好设置里,在 Profiles 里编辑你的配置,在配置右侧的 General 选项卡里,Command 里选择为 Command,然后里边写入 /usr/bin/login -pfq xxx 其中 xxx 是你的用户名。


iterm2的首选项配置


缺点:你失去了「new iterm2 tab here」,即每次打开都是home位置,不能指定文件夹打开终端了,so不建议...

3. 正经地对Zsh进行速度分析和优化

3.1 测算优化前Zsh启动速度

$ \time zsh -i -c exit
        11.62 real         8.23 user         2.29 sys

可以看到,zsh 启动时间需要11.62 秒,so bad, Bro. 作为对比,不加载任何启动命令脚本的 zsh 启动速度飞快,甚至只需要 0.01 秒:

$ \time zsh --no-rcs -i -c exit
        0.01 real         0.00 user         0.00 sys

3.2 优化计划

一个合理而可以达到的目标对速度优化也至关重要。目标是不修改第三方代码的情况下,将加载时间优化到一秒以内,而尽量不损失任何功能。评估性能优化的方法,以 time 测算的时间为准。

3.3 找到速度瓶颈

找到速度瓶颈的方法通常是运行“性能评估”,也就是 Profile。由于 zshrc 是一个 bash 脚本,我需要寻找一些 zsh 脚本的 profile 方法。

可以参考Profiling zsh shell scripts 这篇文章。按照文章中描述的方法,我们在 .zshrc 的最前面加入:

PS4=$'\\\011%D{%s%6.}\011%x\011%I\011%N\011%e\011'
exec 3>&2 2>/tmp/zshstart.$$.log
setopt xtrace prompt_subst

在末尾加入:

unsetopt xtrace
exec 2>&3 3>&-

然后执行 zsh -i -c exit 让 zsh 运行一遍初始化。执行完成后,你应该可以在 /tmp 下看到输出的结果:

$ ls -l /tmp/zshstart*.log
-rw-r--r--  1 fzy  wheel  1043172 Jun  6 19:31 /tmp/zshstart.4249.log

这个日志文件已经可以看了,只不过,人类似乎很难阅读……万幸的是,文章的作者也给出了一个工具,用于把输出的文件转换为KCachegrind 可读的callgrind 文件。然而,它是 OCaml 写的,也没有提供预编译二进制文件,我们必须先安装 OCaml 来编译运行它。为了速度,那就装吧!

以我所用的macOS为例(Linux类似):

brew install ocaml
brew install opam
brew install qcachegrind --with-graphviz

处理一下 /tmp/zshstart.4249.log文件

opam init # 完了,我们还没开始优化,又有一个程序往 .zshrc 里写东西了……这就是为什么它越来越卡
eval `opam config env`
opam install ocamlfind

然后使用作者提供的工具 zshprof 将日志文件生成 callgrind 文件,并使用 QCacheGrind 打开它:

git clone https://github.com/raboof/zshprof.git
cd zshprof

# ocamlfind ocamlopt -linkpkg -thread -package str ZshXtraceToCallgrind.ml
ocamlfind ocamlopt -linkpkg Callgrind.ml -linkpkg ZshXtrace.ml -thread -package str ZshXtraceToCallgrind.ml
./a.out < /tmp/zshstart.4249.log > zsh.callgrind
qcachegrind zsh.callgrind

这时候终端会自己调用弹出qcachegrind的GUI界面,按照micros排序


左侧是性能占用大的文件排序,右上方是占用性能的代码块


比如在.zshrc中的nvm这块代码就占用了很多性能


很显然,大量类似 nvm 这样的版本管理工具初始化命令和他们的补全函数消耗了绝大多数时间。我们就从这些函数入手,优化我们的 shell 加载速度。

3.4 移除影响效率的命令

  1. .zshrc下直接注释掉,因为这个nvm的版本控制我很少用
# export NVM_DIR="$HOME/.nvm"
 #  . "/usr/local/opt/nvm/nvm.sh"
  1. .bash_profile下的anaconda的版本搜索命令也直接注释。。。我发现anaconda真的是一大拖时间的罪魁祸首,必须拿下

3.5 优化结果

$ \time zsh -i -c exit
        0.78 real         0.42 user         0.27 sys

效果显著!55555,我打开Zsh再也不难受了,尽管并不会对我写代码有任何激励作用...枯了

更多优化方法,可以看下面的链接(^-^)

参考链接

编辑于 2021-03-18 23:19