1. 为啥要解决这个问题?
我的zsh
打开实在是太太太太卡了,卡哭…严重影响了我的工作效率
Q:那么为啥会卡呢?
A:好问题!因为.zshrc
里有太多太多的各类语言、启动逻辑和环境变量的配置,所以卡的一批。
2. 一个优化的小tip,针对iterm2
进入 iTerm2 的偏好设置里,在 Profiles 里编辑你的配置,在配置右侧的 General 选项卡里,Command 里选择为 Command,然后里边写入 /usr/bin/login -pfq xxx 其中 xxx 是你的用户名。
缺点:你失去了「new iterm2 tab here」,即每次打开都是home位置,不能指定文件夹打开终端了,so不建议…
3. 正经地对Zsh进行速度分析和优化
3.1 测算优化前Zsh启动速度
1 | $ \time zsh -i -c exit |
可以看到,zsh 启动时间需要11.62 秒,so bad, Bro. 作为对比,不加载任何启动命令脚本的 zsh 启动速度飞快,甚至只需要 0.01 秒:
1 | $ \time zsh --no-rcs -i -c exit |
3.2 优化计划
一个合理而可以达到的目标对速度优化也至关重要。目标是不修改第三方代码的情况下,将加载时间优化到一秒以内,而尽量不损失任何功能。评估性能优化的方法,以 time 测算的时间为准。
3.3 找到速度瓶颈
找到速度瓶颈的方法通常是运行“性能评估”,也就是 Profile。由于 zshrc 是一个 bash 脚本,我需要寻找一些 zsh 脚本的 profile 方法。
可以参考Profiling zsh shell scripts 这篇文章。按照文章中描述的方法,我们在 .zshrc 的最前面加入:
1 | PS4=$'\\\011%D{%s%6.}\011%x\011%I\011%N\011%e\011' |
在末尾加入:
1 | unsetopt xtrace |
然后执行 zsh -i -c exit
让 zsh 运行一遍初始化。执行完成后,你应该可以在 /tmp 下看到输出的结果:
1 | $ ls -l /tmp/zshstart*.log |
这个日志文件已经可以看了,只不过,人类似乎很难阅读……万幸的是,文章的作者也给出了一个工具,用于把输出的文件转换为KCachegrind
可读的callgrind
文件。然而,它是 OCaml
写的,也没有提供预编译二进制文件,我们必须先安装 OCaml
来编译运行它。为了速度,那就装吧!
以我所用的macOS
为例(Linux类似):
1 | brew install ocaml |
处理一下 /tmp/zshstart.4249.log
文件
1 | opam init # 完了,我们还没开始优化,又有一个程序往 .zshrc 里写东西了……这就是为什么它越来越卡 |
然后使用作者提供的工具 zshprof 将日志文件生成 callgrind 文件,并使用 QCacheGrind 打开它:
1 | git clone https://github.com/raboof/zshprof.git |
这时候终端会自己调用弹出qcachegrind
的GUI界面,
很显然,大量类似 nvm 这样的版本管理工具初始化命令和他们的补全函数消耗了绝大多数时间。我们就从这些函数入手,优化我们的 shell 加载速度。
3.4 移除影响效率的命令
.zshrc
下直接注释掉,因为这个nvm
的版本控制我很少用
1 | # export NVM_DIR="$HOME/.nvm" |
.bash_profile
下的anaconda
的版本搜索命令也直接注释。。。我发现anaconda
真的是一大拖时间的罪魁祸首,必须拿下
3.5 优化结果
1 | $ \time zsh -i -c exit |
效果显著!55555,我打开Zsh
再也不难受了,尽管并不会对我写代码有任何激励作用…枯了
更多优化方法,可以看下面的链接(^-^)