99

ZSH takes about a second and a half from creating a new terminal window to being ready. I'm pretty sure that the culprit is compinit.

I haven't been able to find good documentation on compinit, but it looks like it should be caching all of the necessary things in some file like .zcompdump.

Any tricks on speeding it up?

1

15 Answers 15

43

oh-my-zsh was taking about 1.5 seconds to start up on my laptop. I wrote up some of the steps I took to get that down to about 0.25 seconds.

Another kind soul summarized the steps required to integrate my changes into your copy of oh-my-zsh.

The biggest problem is that compinit was being called a whole bunch of extra times instead of just one time after the fpath was completely defined. I made those changes on my branch of oh-my-zsh on github. The changes have been discussed on github and they seem to be working well for a few people. Hopefully the changes will be merged into oh-my-zsh in the near future.

5
  • 7
    For future readers, I believe all these changes have now been merged upstream. May 12, 2012 at 23:41
  • 2
    Changes may have been moved upstream, but removing Git from plugins has helped me substantially. Jun 15, 2012 at 12:57
  • 2
    I have the newest version of oh-my-zsh, no changes, takes 20 seconds to start.
    – gman
    Dec 31, 2020 at 7:14
  • Removing plugins worked like charm, removed all except git.
    – Raja G
    Jan 5, 2023 at 8:40
  • if you want to remove git plugin for specific repo or global 🧤 github.com/ohmyzsh/ohmyzsh/issues/3288#issuecomment-585201848 Feb 10, 2023 at 9:18
40

While ZSH has it's own fair-share of slowdowns, if you find the terminal window blank for a few moments before you see the Last Login: line, you are going to need to clear your log files to see speed improvements. This is still an issue as of OSX Lion and will need to be done every several months. Lame, I know.

The command is:

sudo rm -rf /private/var/log/asl/*.asl

Of course, you need to read this article beforehand and so you know exactly what is going on, because running anything that says sudo rm needs to be thought about. I only put this here because your use of ZSH proves your competence with the command line to start.

5
  • 1
    Thanks, such a simple solution for something that's been plaguing me for so long!
    – Dean
    Jun 27, 2013 at 15:35
  • 16
    I'd recommend not using -r since no directories are involved and it sn't needed. Omitting it leads to less tears if someone types sudo rm -rf / private/var/log/asl*.asl (space before private) by mistake.
    – Dean
    Jun 27, 2013 at 15:39
  • 5
    Or even more foolproof, cd /private/var/log/asl then rm -f *.asl. Also for the record, this answer saved me from a startup time that was approaching 10 seconds, thanks a lot!
    – veryDisco
    May 12, 2016 at 22:19
  • 2
    Worked for me! BTW trash /private/var/log/asl*.asl. trash will need to be installed, of course. brew install trash
    – Mike D
    Jan 16, 2017 at 13:26
  • 1
    @MikeD that should be trash /private/var/log/asl/*.asl (missed slash)
    – tdc
    Jun 10, 2020 at 15:46
32

In my case, NVM was making it slow.

Original code (at .bash_profile, .zshrc loads my bash_profile)

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  # This loads nvm bash_completion

I've changed it to:

export NVM_DIR="$HOME/.nvm"
#[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  # This loads nvm bash_completion
alias nvm="unalias nvm; [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"; nvm $@"

Added the alias (last line), so I will only load NVM when I try to use it. It decreased the load time from 1.5 to 0.2 seconds.

/usr/bin/time zsh -i -c exit #If you want to time yours
4
  • 2
    This was the case for me too. Worth mentioning that any other version manager will likely also impact startup time (jenv, pyenv, rbenv...).
    – Marino
    Feb 20, 2021 at 16:50
  • 1
    This is a life saving. I was using both nvm and pyenv, both is time consuming.
    – hunzter
    Nov 19, 2021 at 7:15
  • this worked for me too
    – SanS
    May 6, 2022 at 15:07
  • This doesn't work for me. Running node or npm result in command not found until nvm is invoked for the first time.
    – varogen
    Aug 16, 2023 at 21:22
15

My biggest improvement has come from removing items from the plugin=() section. The 'github' and 'brew' plugins are very slow to load.

I also removed hub which I had aliased togitand that sped up the prompt as well.

I've been using '/usr/bin/time zsh -i -c exit' to record the startup times, however compinit doesn't appear to make a big enough difference for me.

It'd be great to hear what others are doing to speed it up.

2
  • 1
    Removing the github and brew plugins solved my problem immediately. Nov 15, 2011 at 3:02
  • git and brew plugins are quite essential to me. By removing ruby plugin solved my problem. Thanks.
    – Ivan Xiao
    Mar 19, 2012 at 17:30
9

Are you using the pre-installed /bin/zsh or another one? I ask, because the zsh I have installed through fink starts terribly slow due its inclusion of zsh templates, while the vanilla starts right up.

Does running with an explicit dumpfile (compinit -d dumpfile) make it go faster? The man page states that

The next invocation of compinit will read the dumped file instead of performing a full initialization.

1
  • 2
    I am using Oh My Zsh (which I believe uses the default /bin/zsh). When I disable loading all of Oh My Zsh's plugins and whatnot, it loads up really quickly, but I think in that case compinit is never called. When I manually call compinit it takes a little while. Maybe it's just because Oh My Zsh adds so many bindings to compinit?
    – Eli
    Jan 24, 2011 at 17:16
8

Zsh on its own starts up in around 0.1 second for me, which is plenty good enough. I just noticed as I got near the 50,000 command history mark that it became more like 3 seconds to load up the first prompt.

I dunno how you guys are finding all these other reasons for slow startup, but mine was exactly what my first guess was. I did a mv ~/.zsh_history zsh_history_backup and bam, 3 second startup is now 0.1 second startup. Curiously, /usr/bin/time /bin/zsh -i -c exit fails to capture the time it takes to load in the history.

If you don't have tens of thousands of commands in your zsh history, though, then this isn't it. My ~/.zsh_history measured 1.8MB. Its very possible to accidentally paste a large chunk of stuff as a command into a terminal, this will also bloat history up right quick (though this is something very much to avoid doing as it can obviously be extremely destructive).

1
  • This is the answer. If haven't done anything fancy (a lot of plugins and addons) with oh-my-zsh, then I guarantee it's because of the history log. The change is immediate. Nov 16, 2016 at 17:43
6

Now oh-my-zsh checks special git configuration option oh-my-zsh.hide-status before querying status. So run

git config oh-my-zsh.hide-status 1

on problematic repository.

1
  • for me I had to disable the git plugin in .zshrc. I am currently facing issues with slow internet response, which made zsh slow
    – Paschalis
    Aug 12, 2016 at 2:02
2

I was using the theme "af-magic"

Switching to "muse" solved the issue.

Edit ~/.zshrc and modify that line:

#ZSH_THEME="random"
#ZSH_THEME="af-magic"
ZSH_THEME="muse"
1
  • thanks for the answer, I found changing from af-magic to something else has solved for the problem. Interestingly restoring back af-magic still works great. not sure what went on under the hood.
    – sarat
    Jan 22, 2016 at 5:11
1

These are the steps which I have used to optimize my shell startup speed and reducing lag in executing commands -

  1. If you are using powerlevel9k, then I will recommend to immediately switch to powerlevel10k.

Powerlevel10k is a theme for Zsh. It emphasizes speed, flexibility and out-of-the-box experience. It is a reimplementation of the popular Powerlevel9k zsh theme. It looks exactly the same given the same configuration but renders prompt 10-100 times faster. It's optimized on every level of the stack, all the way down to using a patched version of libgit2 that can scan a repo 4 times faster than the original. It can remove Zsh startup lag even if it's not caused by a theme with features such as Instant Prompt.

  1. Go to Preferences -> Profiles -> General -> Command and select the option Command instead of Login Shell and paste the below command in the box nearby it.
login -pfq username /usr/local/bin/zsh -il

You wouldn't see the last login time printed when starting a new tab now. If zsh is not present in the location /usr/local/bin/zsh, you will need to install zsh using brew. The default zsh provided by mac is at /usr/bin/zsh and might be using an older version like 5.2 which can cause slow speed when used with iTerm or oh-my-zsh.

  1. To make pasting in zsh fast, execute the below command in the terminal.
mkdir -p $ZSH_CUSTOM/lib && touch $ZSH_CUSTOM/lib/misc.zsh
  1. Point 2 should already take care of slow login times. But just for safety execute the below command
mkdir -p .hushlogin
  1. There are tons of plugins you might be using which are slow and creates lag. You need to point out these plugins and remove them. For this, you will need zsh profiling. Follow this link for more details -

https://stevenvanbael.com/profiling-zsh-startup

1
  • Welcome to Super User! Please do not post the same answer to multiple questions. If the same information really answers both questions, then one question (usually the newer one) should be closed as a duplicate of the other. You can indicate this by voting to close it as a duplicate or, if you don't have enough reputation for that, raise a flag to indicate that it's a duplicate. Otherwise tailor your answer to this question and don't just paste the same answer in multiple places.
    – DavidPostill
    Mar 28, 2020 at 7:13
1

I added zmodload zsh/zprof to start and zprof to end of my ~/.zshrc file. Then I ran exec zsh to reload session. It turned out is_update_available was taking 95% of load time. I disabled auto-update by DISABLE_AUTO_UPDATE="true" in my .zshrc file. Then ran exec zsh and my problem was solved

1
  • Had the same problem when building zsh from source. Disabling auto-update did the trick as well.
    – Stefan B
    Nov 24, 2022 at 15:27
0

I have really great speed improvements after clearing ~/.oh-my-zsh/plugins/ directory. There was many unused plugins inside it.

0

Add the following to your ~/.zshenv

skip_global_compinit=1
0

Many of the above answers are either:

  • old, and possibly have been merged into upstream already, or
  • rely on you disabling plugins that you might need later

I found a great article from 2020 by mjclemente that helped me to use plugins such as evalcache and zsh-nvm to speed up shell load time from ~1.65s to 0.6s without disabling any plugins: Speeding Up My Shell (Oh My Zsh)

Hope it helps someone else!

0

I stupidly had this line.

# pyenv
echo 'eval "$(pyenv init --path)"' >> ~/.zprofile

So it got slower and slower every time I opened a new terminal Tab. I had 76 times that line in .zprofile 🤦

1
  • Ahhh this was what solved it for me! I had echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> /Users/aidanlister/.zprofile in my .zshrc. My .zprofile had thousands of lines of that in it. I deleted all but the first line from .zprofile, and commented out the offending line in my .zshrc, and now my terminal is fast again!
    – Aidan
    Feb 11, 2022 at 2:19
0
  1. Produce new dumped configuration

    rm ~/.zcompdump
    compinit
    

    Doing that, in my case, sped it up from 10 to 0.5 seconds. If someone knows why, please do let me know.

  2. Reduce search path for function definitions. compinit's hot run time increases with the size of fpath, according to my own benchmark:

    for x in {1..5}
    do
      for run in cold 'hot '
      do
        print -n "$run ${#fpath} \t"
        time (compinit)
      done
      fpath=($fpath $fpath)
    done
    
    cold 24  ( compinit; )  2,86s user 0,64s system 99% cpu 3,502 total
    hot  24  ( compinit; )  0,12s user 0,04s system 99% cpu 0,160 total
    cold 48  ( compinit; )  5,63s user 0,68s system 99% cpu 6,319 total
    hot  48  ( compinit; )  0,24s user 0,06s system 99% cpu 0,304 total
    cold 96  ( compinit; )  12,82s user 0,87s system 99% cpu 13,705 total
    hot  96  ( compinit; )  0,59s user 0,13s system 99% cpu 0,725 total
    cold 192     ( compinit; )  35,63s user 1,19s system 99% cpu 36,885 total
    hot  192     ( compinit; )  1,60s user 0,24s system 99% cpu 1,844 total
    cold 384     ( compinit; )  119,37s user 2,47s system 99% cpu 2:02,18 total
    hot  384     ( compinit; )  5,02s user 0,48s system 99% cpu 5,508 total
    
  3. Disable important security checks using flag -C. That will make your setup more vulnerable and faster, according to zshcompsys(1), section "Use of compinit"

    time (compinit)
    ( compinit; )  0,19s user 0,30s system 98% cpu 0,493 total
    
    time (compinit -C)
    ( compinit -C; )  0,08s user 0,02s system 97% cpu 0,097 total
    

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .