Z Shell Performance
My zsh is taking so long to launch now, like up to 40 seconds, and I wanted to find out why.
So I did some Googling and found out that adding zmodload zsh/zprof to the top of my .zshrc file meant that I could run zprof (after reloading the shell). This yielded:
| num | calls | time | self | name | ||||
|---|---|---|---|---|---|---|---|---|
| 1) | 1 | 3067.88 | 3067.88 | 74.90% | 1344.09 | 1344.09 | 32.82% | nvm_auto |
| 2) | 2 | 909.13 | 454.57 | 22.20% | 909.13 | 454.57 | 22.20% | jenv |
| 3) | 2 | 1723.79 | 861.90 | 42.09% | 852.65 | 426.32 | 20.82% | nvm |
| 4) | 1 | 779.97 | 779.97 | 19.04% | 710.71 | 710.71 | 17.35% | nvm_ensure_version_installed |
| 5) | 1 | 90.30 | 90.30 | 2.20% | 72.26 | 72.26 | 1.76% | nvm_die_on_prefix |
| 6) | 1 | 69.26 | 69.26 | 1.69% | 69.26 | 69.26 | 1.69% | nvm_is_version_installed |
| 7) | 1 | 47.94 | 47.94 | 1.17% | 47.94 | 47.94 | 1.17% | handle_completion_insecurities |
| 8) | 1 | 18.56 | 18.56 | 0.45% | 18.56 | 18.56 | 0.45% | compinit |
| 9) | 2 | 17.09 | 8.54 | 0.42% | 17.09 | 8.54 | 0.42% | nvm_grep |
| 10) | 2 | 12.73 | 6.36 | 0.31% | 12.73 | 6.36 | 0.31% | grep-flag-available |
| 11) | 2 | 11.29 | 5.65 | 0.28% | 11.29 | 5.65 | 0.28% | down-line-or-beginning-search |
| 12) | 1 | 4.79 | 4.79 | 0.12% | 4.77 | 4.77 | 0.12% | powerlevel9k_vcs_init |
| 13) | 1 | 4.67 | 4.67 | 0.11% | 4.67 | 4.67 | 0.11% | termColors |
| 14) | 2 | 2.91 | 1.45 | 0.07% | 2.91 | 1.45 | 0.07% | env_default |
| 15) | 15 | 2.05 | 0.14 | 0.05% | 2.05 | 0.14 | 0.05% | up-line-or-beginning-search |
…which showed that nvm is taking a long time to load. I don’t use it a lot but I do want it sometimes so instead I’m using https://github.com/lukechilds/zsh-nvm#lazy-loading which lazy-loads nvm with some additions in the .zshrc file:
export NVM_LAZY_LOAD=true
export NVM_COMPLETION=true
plugins=(zsh-nvm [plus your others])
It’s gone from around 40 seconds to around 4 seconds!
However rbenv and jenv are also slow! I couldn’t find a reasonably easy way to improve that but I am using evalcache which will cache the init commands, saving some time.
Installed with:
git clone https://github.com/mroth/evalcache ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/evalcache
…and in .zshrc:
plugins=(evalcache [plus your others])
Then instead of eval "$(jenv init -)" in your .zshrc use _evalcache jenv init -
Sadly that’s one less excuse though…
