Little Thing #2 — Speeding up ZSH

Danny Smith
Aug 9, 2018 · 3 min read

This is part of my Little Things series.

Three years ago, I switched my shell from bash to zsh. Since then, I’ve added a bunch of stuff to my dotfiles and I’ve been getting increasingly annoyed that my shell is slow to load.

Today, I opened a new tab in iterm and ended up waiting about 15 seconds before I had a usable prompt.

Time to fix that

$(which zsh) -lxv

First off, it was obvious there was a lot going on. I use Oh My ZSH, so lots of it was coming from there and the plugins I have installed. The other obvious sticking point was nvm. Not only was there loads of nvm-looking stuff, but it clearly spent a long time executing this line in my zshrc

"$(brew --prefix nvm)/nvm.sh"

This is a good hint, but to be sure, I switched on profiling with zprof.

zmodload zsh/zprof # top of your .zshrc file# Your .zshrc stuffzprof # bottom of .zshrc
I forgot to take a screenshot of the output at the beginning, so this is mid-way through my optimisations 🙃

The results pretty much confirmed mysuspicionss.

  1. NVM-related stuff was taking ages.
  2. Something called compaudit and compinit were also taking ages.

Fixing NPM

Second, I was calling this, to make nvm available as a command:

"$(brew --prefix nvm)/nvm.sh"

Not only is the nvm.sh script itself pretty slow, but brew command takes about a second. It turns out that NVM isn’t actually an executable — it’s just a shell function. You can see that if you run which nvm.

The obvious thing to do was create a nvm() function in .zshrc . If the script has never been run we should unset our nvm() function and run it, then cal; nvm with the arguments it was originally called with…

nvm() {
echo "🚨 NVM not loaded! Loading now..."
unset -f nvm
export NVM_PREFIX=$(brew --prefix nvm)
[ -s "$NVM_PREFIX/nvm.sh" ] && . "$NVM_PREFIX/nvm.sh" nvm "$@"
}

This worked, but it occured to me that I probably want NVM available when I call any node-based command (things like create-react-app).

TIME TO RUN FOR GOOGLE 🏃‍

This pretty much does what’s needed…

Sorted.

What else is slow then?

autoload -Uz compinitfor dump in ~/.zcompdump(N.mh+24); do
compinit
done
compinit -C

Anything Else?

If you want to go a bit further, Carlos Alexandro Becker wrote a decent article on the subject:


Danny Smith

Written by

Software Engineer and Teacher. Passionate about technology education and helping people be happy at work. I also play blues music.