Back
3 min read

How fast is your shell? →

Thorsten Ball:

Now you’re thinking: does it matter? 100ms? 200ms? Come on, dude.

And I’m telling you: yes it matters. Of course it matters. Those who don’t honor the milliseconds will end up with seconds. 100%, it absolutely matters. Who wants to walk around with clown shoes full of lead?

Think about it this way: which program do you execute more often than your shell? How many shells do you spawn every day? How many other programs do you run every day that spawn your shell? If you’re anything like me, it’s a lot of shells per day. I’m a heavy terminal and tmux user. I spawn shells like I open new tabs in a browser. Do you want one of your most-used programs to start slow because you didn’t care?

If there's one thing I utterly hate, it must be lagging in my terminal. It's infuriating. At one point in life I noticed that whenever I was creating new tab or split in iTerm, my shell needed good 1-2 seconds to actually get going. Once I started looking into it there was no way back — I had to have immediately responsive shell, no compromises here. That's how I landed on fish as it has sensible defaults, you can lazy load almost anything and it's lightning fast. The price to pay for this is lack of being POSIX compatible and alternative, slightly pythonic syntax for its commands. Globbing especially was getting in my way and I could never remember what I needed to escape, where and why.

Every now and then I was entertaining the idea of going fully in with ZSH, but usually when I was running the speed comparison, fish was obliterating any competition. That was until I god my hands on Zim! I have no idea what's going on under the hood of this, but when it's in use, ZSH can pick up the fight:

$ for i in {1..10} ; do time zsh -i -c exit ; done
zsh -i -c exit  0.03s user 0.03s system 85% cpu 0.071 total
zsh -i -c exit  0.02s user 0.03s system 88% cpu 0.059 total
zsh -i -c exit  0.02s user 0.03s system 89% cpu 0.058 total
zsh -i -c exit  0.02s user 0.03s system 89% cpu 0.058 total
zsh -i -c exit  0.02s user 0.03s system 89% cpu 0.058 total
zsh -i -c exit  0.02s user 0.03s system 88% cpu 0.060 total
zsh -i -c exit  0.02s user 0.03s system 89% cpu 0.059 total
zsh -i -c exit  0.02s user 0.03s system 89% cpu 0.059 total
zsh -i -c exit  0.02s user 0.03s system 89% cpu 0.058 total
zsh -i -c exit  0.02s user 0.03s system 90% cpu 0.058 total

And here's fish:

$ for i in {1..10} ; do time fish -i -c exit ; done
fish -i -c exit  0.02s user 0.02s system 77% cpu 0.040 total
fish -i -c exit  0.01s user 0.01s system 79% cpu 0.031 total
fish -i -c exit  0.01s user 0.01s system 78% cpu 0.029 total
fish -i -c exit  0.01s user 0.01s system 80% cpu 0.029 total
fish -i -c exit  0.01s user 0.01s system 79% cpu 0.029 total
fish -i -c exit  0.01s user 0.01s system 78% cpu 0.030 total
fish -i -c exit  0.01s user 0.01s system 79% cpu 0.029 total
fish -i -c exit  0.01s user 0.01s system 79% cpu 0.029 total
fish -i -c exit  0.01s user 0.01s system 78% cpu 0.029 total
fish -i -c exit  0.01s user 0.01s system 78% cpu 0.029 total

While fish does seem to be still faster, it doesn't really matter at this point — the difference is unnoticeable to the naked eye. I also toyed a bit with hyperfine to have a bit better control over the comparison and in some tests ZSH was faster than fish:

How do you fix your slow shell startup time?

Thorsten has some good ideas on how to make it faster so be sure to check out his post — I only wanted to put Zim on your radar as it was a total win in my book 👌🏻