Blazingly Fast Spacemacs with Persistent Server

I’ve been spending my time getting used to Spacemacs for my main editor. The slowness of its startup time could rival Atom, but it shouldn’t be! In this post I’ll go through how I make my Spacemacs start in milliseconds.

If you haven’t heard of Spacemacs before, it’s an Emacs distribution built to end the holy war of Vim vs. Emacs by integrating the best of both worlds. If you’re a hardcore Vim user, using Spacemacs will make you feel right at home. Among others, it provides the ergonomic and productive Vim keybindings on top of the powerful Emacs platform, while also providing discoverability of the keybindings through the SPC leader key. Neat.

(I’m not a good marketer, so there’s a pretty good chance that you don’t buy my pitch, but please visit the official site and have a look around!)

This post assumes the following:

  • You have Emacs ≥ 24.x installed
  • You have Spacemacs installed

Okay, let’s get on with it!

Oh, the slowness!

After Spacemacs is successfully installed, each time you start Emacs you would be greeted by a long startup time. Indeed, the main Spacemacs buffer tells me the following:

251 packages loaded in 10.237s (e:193 r:2 l:10 b:46)

Believe it or not, on my machine sometimes it takes ~10 seconds to start a new Emacs instance. Preposterous! It’s even on par with Atom, but Atom has the excuse of it being an Electron app. It doesn’t make any sense.

So I dug around the internet looking for a way to speed up things. My goal was to see if I could make it open faster than Sublime Text, and we know how blazingly fast Sublime is. Note that I’m basically an Emacs noob so I don’t have any idea where to look.

And finally, it turns out that, just as with most of the things in my life, I’ve been doing it all wrong.

Hello, Emacs server!

When you install Emacs, there’s also this little binary that got distributed alongside it called emacsclient, and that is the most powerful hint. It appears that Emacs is meant to be used as a persistent server daemon, where you can connect to it to edit files.

I’ve come across this post that says it is best practice to leave an editor instance running, and use the emacsclient program to connect to it. Sadly, I’m a bit of a clean freak and I don’t like idle windows cluttering my desktop. What’s even more annoying, if you accidentally close the window (or frame as we call it in Emacs world), you have to go through the painful startup process again.

Luckily, I can accommodate my clean-freak trait. There are two steps involved: writing a shell script and overriding a default keybinding.

The `em` shell script

Emacs has a flag that lets it run as a server in the background, by using emacs --daemon. It is also nice that if you run emacsclient -a '', if there isn’t an Emacs daemon running, it will start one (basically calling emacs --daemon) and connect to it.

So I’ve written the following shell script (inspired by this superuser question) called em that takes care of things for me:

#!/usr/bin/env zsh
# Checks if there's a frame open
emacsclient -n -e “(if (> (length (frame-list)) 1) ‘t)” 2> /dev/null | grep t &> /dev/null
if [ “$?” -eq “1” ]; then
emacsclient -a ‘’ -nqc “$@” &> /dev/null
else
emacsclient -nq “$@” &> /dev/null
fi

The script will check if there’s an Emacs frame (window) open. If there isn’t one, it will run emacsclient -a '' -nqc "$@", which will start the Emacs daemon if necessary and create a new frame (via the -c option), passing the arguments given to the script. Else, it will just call emacsclient sans the -c flag to open the given file in an already open frame. I just need one open frame at a time.

With this script, I can edit any file using the command em anyfile.anyext from my terminal. Great, but not enough!

Making sure that closing a frame doesn’t kill Emacs

The previous shell script will make sure that it will start a daemon if it doesn’t exist. However, closing a frame created by emacsclient will still kill the daemon. Urgh! It’s no different than the original solution from the above post.

There’s a command, called spacemacs/frame-killer, that will just kill the frame without killing the daemon. Unfortunately, it is bound to SPC q z, which is arguably not the most ergonomic key combo ever. It’s hard to hit the q z stroke with your left hand, so I wanted to rebind it to something else.

Spacemacs has the commands spacemacs/kill-emacs, which is bound to SPC q Q, and spacemacs/prompt-kill-emacs, bound to SPC q q. I don’t get the difference between the two, and it seems redundant, so I think SPC q q will serve well as the alternative that I can bind frame-killer to.

I rebind it by adding the following snippet into the body of dotspacemacs/user-config function in my .spacemacs file:

(evil-leader/set-key
“q q” ‘spacemacs/frame-killer)

Don’t forget to reload the configuration with SPC f e R after modifying it. Now SPC q q will behave as frame-killer, and I can still use SPC q Q if for whatever reason I need to kill the Emacs daemon. What’s also great is that Vim’s :q behaves just like frame-killer. Nice!

Putting it into practice

So let’s compare it. With no Emacs daemon running, Let’s start Emacs and see how long it takes:

$ time em
em 0.01s user 0.02s system 0% cpu 8.835 total

Yikes, nearly 9 seconds to an open frame. Let’s close the frame with SPC q q and try that again:

$ time em
em 0.01s user 0.01s system 17% cpu 0.100 total

It now takes just 0.1 seconds to an open frame. Talk about major improvement!

Conclusion

Trying out editors has been a bimonthly habit of mine this past year. This is actually my second time having a look at Spacemacs, and this discovery of making it just as fast as Sublime might actually be the thing that take me away from my current favorite editor for years, Atom.

In this post I’ve managed to cut down startup time by starting Emacs as a persistent server daemon and using the emacsclient binary to connect to it. I also rebind SPC q q to close a frame without killing the Emacs daemon, so that subsequent Emacs invocation would take less than a second to open.

With this setup, I can keep my desktop clean and be sure that whenever I want to edit anything, the Emacs daemon will have my back.