诊断命令

# 测试 interactive shell 启动时间
time zsh -i -c exit
 
# 测试 login shell 启动时间(会额外加载 ~/.zprofile)
time zsh -l -i -c exit
 
# 检查当前是否为 login shell
echo $0   # 输出 -zsh = login shell,zsh = 非 login shell

逐文件计时

for f in ~/.zshenv ~/.zprofile ~/.zshrc ~/.zlogin; do
  if [ -f "$f" ]; then
    start=$(python3 -c "import time; print(time.time())")
    zsh -c "source $f" 2>/dev/null
    end=$(python3 -c "import time; print(time.time())")
    echo "$f: $(python3 -c "print(f'{($end-$start)*1000:.0f}ms')")"
  fi
done

常见瓶颈

来源典型耗时说明
oh-my-zsh core~200ms基础框架开销
spaceship theme~120ms功能丰富但慢
zsh-syntax-highlighting~100ms每次初始化
zsh-autosuggestions~60ms相对较小
nvm 直接 source~200ms最常见的大坑

优化方案

1. 换轻量 prompt 框架(收益最大)

把 oh-my-zsh 整体换成 Starship,启动时间可降至 50-100ms:

brew install starship
# 在 .zshrc 末尾替换原有 theme 配置
eval "$(starship init zsh)"

2. 保留 omz 但换轻量 theme

spaceship 换成 robbyrussell 可节省约 120ms。

3. nvm 懒加载

nvm 直接 source 约 200ms,改为懒加载只在首次调用时初始化:

export NVM_DIR="$HOME/.nvm"
_nvm_load() {
  unset -f nvm node npm npx yarn pnpm
  [ -s "$NVM_DIR/nvm.sh" ] && source "$NVM_DIR/nvm.sh"
  [ -s "$NVM_DIR/bash_completion" ] && source "$NVM_DIR/bash_completion"
}
nvm()  { _nvm_load; nvm  "$@"; }
node() { _nvm_load; node "$@"; }
npm()  { _nvm_load; npm  "$@"; }
npx()  { _nvm_load; npx  "$@"; }

4. compinit 缓存优化

每天只重建一次 dump,避免每次启动都全量扫描:

autoload -Uz compinit
if [ $(date +'%j') != $(stat -f '%Sm' -t '%j' ~/.zcompdump 2>/dev/null) ]; then
  compinit
else
  compinit -C
fi

也可配合 ZSH_DISABLE_COMPFIX=true 跳过安全检查加速。

5. 关闭不必要的 oh-my-zsh 插件

只保留常用插件,每个插件都有启动开销:

# 重量级插件建议懒加载
plugins=(git)   # 最小化配置

参考时间基准

  • 正常范围:< 200ms
  • 可接受:200-500ms
  • 需要优化:> 500ms
  • 优化后目标:< 100ms(Starship 方案)