bikeshed.coffee

zsh startup slowness

For a while now I've felt like my zsh has been starting up more and more slowly. It's one of those small annoyances that builds up over time, especially if you pop a lot of shells via e.g. tmux and have to wait more than "One Mississippi" to do anything. This week I finally got annoyed enough to do something about it.

before

Step one is to figure out exactly how slow and why. First I timed the init:

$ time zsh -i -c exit
0.71s user 0.58s system 52% cpu 2.479 total`

... Two and a half seconds?? Ouch.

Next was to figure out what was causing the slowness via the profiler:

# in .zshrc...
zmodload zsh/zprof
# rest of config file
zprof

This gets zsh to print out a breakdown of resource use for everything in .zshrc. The output looks something like:

num  calls                time                       self            name
-----------------------------------------------------------------------------------
 1)    2         288.03   144.01   20.45%    288.03   144.01   20.45%  compdump
 2)    2         697.50   348.75   49.53%    209.51   104.76   14.88%  compinit
 3)    1         538.85   538.85   38.26%    200.08   200.08   14.21%  nvm_auto
 4)    2         338.77   169.39   24.05%    193.05    96.53   13.71%  nvm
 5) 1563         156.34     0.10   11.10%    156.34     0.10   11.10%  compdef
 6)    1         126.92   126.92    9.01%    114.74   114.74    8.15%  nvm_ensure_version_installed
 7)    4          44.64    11.16    3.17%     44.64    11.16    3.17%  compaudit
 8)    5          34.08     6.82    2.42%     34.08     6.82    2.42%  __rvm_db

tl;dr - the first 25 or so lines for me were dominated by nvm and rvm. Somehow not surprised.

nvm

nvm apparently takes forever for a variety of reasons, so the best course is to only use it when needed. There are manual solutions out there, but I decided to lean into oh-my-zsh and just use the plugin's built-in lazy functionality. After removing the manual nvm install:

# in .zshrc / config
export NVM_LAZY=1
plugins=(nvm)

rvm

rvm is mostly around as cruft I had picked up over the ages. I don't use ruby often (or at all) these days, so I just went ahead and removed it. However, there are other solutions for folks who still need it + want lazy loading.

after

After the above, the time went down to about:

time zsh -i -c exit  0.23s user 0.10s system 101% cpu 0.332 total

Repeated runs showed it mostly starting in .3 - .5 sec. Pretty good, but still plenty of room for improvement.