oh-my-zsh启动加速

本文最后更新于:2022年9月27日 晚上

缘起

最近突然发现 ZSH 的启动速度很慢,受不了了,于是又折腾了一番,进行了一下排查和优化

PS:不想看排查过程的直接点这里

排查

zsh 启动时间

  • 查看 omz 启动过程花费的时间

    1
    2
    3
    for i in {1..10};
    do time zsh -i -c exit; sleep 0.1;
    done;

    启动过程花费
    平均花费时间在 0.5s 左右,确实很慢

  • 查看详细的加载项花费的时间
    跟 C、Python 等语言类似,zsh 提供了专门的 profiling 模块 zprof 用于衡量每个 zsh 函数的执行耗时比例,在 ~/.zshrc 文件第一行添加下列命令加载 zprof

    1
    zmodload zsh/zprof

    然后 source ~/.zshrc 重新加载 zsh 模块
    使用 zprof 命令获取各个函数加载时间
    启动过程花费时间详情
    可以看到前几个都是 nvm,测试一下,注释掉 ~/.zshrcnvm 部分

    1
    2
    3
    4
    # NVM 配置  
    # export NVM_DIR="$HOME/.nvm"
    # [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
    # [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion

    再测试一下加载时间
    启动过程花费时间详情
    加载速度显著提高

优化方案

1. NVM 手动懒加载

把原有的 NVM 配置替换成函数,需要使用时再进行调用

1
2
3
4
5
6
7
# NVM 懒加载 
nvm() {
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion
nvm "$@"
}

缺点是每次使用 npm 前都需要先调用 nvm 进行加载

2. zsh-nvm 插件懒加载

插件安装

1
git clone https://github.com/lukechilds/zsh-nvm ~/.oh-my-zsh/custom/plugins/zsh-nvm

修改 ~/.zshrc 配置,删除原有的 NVM 的启动部分,开启 zsh-nvm 的懒加载

1
2
3
4
5
6
7
# 启用插件
plugins=(
...
zsh-nvm
)
# 开启懒加载
export NVM_LAZY_LOAD=true

效果
效果
确实有显著提升,但是实际体验中每次新建终端还是有明显延迟感
明显延迟感

3. fnm 替代 nvm (最终方案,墙裂推荐)

先放效果图
没有延迟感
加载时间
效果
这回在 zprof 根本看不到 fnm 的影子
效果

fnm 的使用

安装 fnm

fnm 的安装比较简单,一行脚本足矣

1
curl -fsSL https://fnm.vercel.app/install | bash  

安装完毕后会自动配置到 ~/.zshrc 中,如果没有的手动添加以下配置重新加载就可以了

1
2
3
# fnm
export PATH=$HOME/.fnm:$PATH
eval "`fnm env`"

使用 fnm

fnm 使用方式和 nvm 大同小异

1
2
3
4
5
fnm list-remote # 列出所有 node 版本  
fnm install v18.4.0 # 安装对应版本,版本号从 list-remote 获取
fnm default v18.4.0 # 设置全局默认 node 版本
fnm use v16.15.1 # 设置当前终端版本,重启终端后失效
fnm current # 查看当前使用 node 版本

收尾:卸载 nvm

删除 NVM 文件夹,然后删除 ~/.zshrc 中相关配置即可

1
rm -rf ~/.nvm  # 删除 NVM 文件夹  

关于 fnm 和 nvm

其实关于两者的速度差这么多,个人猜测大概的原因就是使用的语言问题了
nvm 用的是 shell,而 fnm 则是使用 Rust 编写的
现在提起 Rust 估计大家第一时间的想到的就是快

为了这点终端启动体验,又花了不少时间,真是充实而又白给的一天
不过这不就是程序员应有的追求吗(笑)

一点小坑

在看 zprof 信息 的时候还注意到了 compdumpcompinit 耗费的启动时间也不少
不过今天就到这了,毕竟程序员的哲学之一不是够用就好,过度优化是万恶之源吗(再笑)
留下一个坑,有空再研究


oh-my-zsh启动加速
https://blog.evil-scream.cn/2022/06/24/oh-my-zsh启动加速/
作者
evil-scream
发布于
2022年6月24日
许可协议