Something that had been irking me for a while was how long Zsh took to load.
“How long” was subjective until I finally decided to profile it.
time zsh -i -c exit
It took nearly 30 seconds to start Zsh — yikes.
What made it even stranger was that I wasn’t using Oh My Zsh with dozens of plugins loaded.
So I set out to fix it.
The first step was figuring out what was slowing startup down. Zsh has a built-in profiler called zprof, which made this surprisingly easy.
# Add to beggining of zshrc
zmodload zsh/zprof
...
# add to the end of zshrc
zprof
It took nearly 30 seconds to start Zsh — yikes.
What made it even stranger was that I wasn’t using Oh My Zsh with dozens of plugins loaded.
So I set out to fix it.
The first step was figuring out what was slowing startup down. Zsh has a built-in profiler called zprof, which made this surprisingly easy.
#before
[ -s "/opt/homebrew/opt/nvm/nvm.sh" ] && \. "/opt/homebrew/opt/nvm/nvm.sh" # This loads nvm
[ -s "/opt/homebrew/opt/nvm/etc/bash_completion.d/nvm" ] && \. "/opt/homebrew/opt/nvm/etc/bash_completion.d/nvm" # This loads nvm bash_completion
eval "$(pyenv init -)"
conda init --all
#after
nvm() {
unset -f nvm node npm npx
source "$NVM_DIR/nvm.sh"
nvm "$@"
}
node() { nvm; node "$@"; }
npm() { nvm; npm "$@"; }
npx() { nvm; npx "$@"; }
pyenv() {
unset -f pyenv
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(command pyenv init -)"
pyenv "$@"
}
conda() {
unset -f conda
source /opt/miniconda3/etc/profile.d/conda.sh
conda "$@"
}
This alone significantly reduced startup time.
I was also able to shave off a couple more seconds by optimizing Zsh completions.
# Before
compinit
#After
compinit -C -u #which skips building the .zcompdump
# Instead use cache
mkdir -p ~/.zsh/cache
zstyle ':completion:*' use-cache true
zstyle ':completion:*' cache-path ~/.zsh/cache
A shell that previously took ~30 seconds to start now feels nearly instant.