Since go 1.14 go released, I’ve had a broken
go-mode setup on my Emacs. I was using
gopls and well, the update broke everything. I initally try to fix it but
I made it worse. At the same time, I started to get fed up with some performance issue of
my configuration and how slow my Emacs starts, about 6s.
I, thus, declared my third Emacs bankruptcy,
:disabled everything and slowly started
from scratch, with the following goal:
- Have it start quick, as less than a second, not too much more than
- Disable anything that I don’t use often initially
- Try to use as much built-in as possible (example: using
Do I really need this feature
Following Protesilaos Stavrou’s emacs videos (and
dotemacs) for a while now, I have a
tendency to try to use built-in feature as much as possible. The most obvious example is
icomplete instead of
When I started my bankruptcy, I disabled every single customization I had, either using
:disabled when using
use-package or the
(when nil) hack. I then started Emacs
and acted on what was missing :
- Do I really miss it ? An example would be, at least initially, the completion in a
gofile. I do miss it, but I miss it way less than having Emacs lagging because of
lsp-modeand showing me wrong completion.
- Is there a built-in option to what I previously used ? Here, the
icompleteexample fits well, or
- Do I need it at startup or on-demand ?
Looking into what takes time
Then, you can do a simple loop:
- Look at the top result
- Fix it (lazy load, removing the feature, …)
Once you have the setup to know what takes time and what not, it’s time to look into how to load the most thing on demand.
use-package is amazing, it tremendously help autoloading modules on-demand. If
you are not using
use-package, usually you are using
require, which loads the
underlying source file (all of it).
use-package, there is multiple ways to load on demand:
:commandsto add callable that will trigger loading the package
:bind-keymap*to bind key sequences to the global keymap or a specific keymap.
:interpreterestablish a deferred binding with the
:hookallows adding functions onto the package hook
:deferis the most generic one, all the previous keyword imply
:defer. You can specify a number of second of idle to load the package.
Once this is done, you are left with edge cases, like
org-babel-do-languages. Those are
to be handle case by case. The good thing about those cases is that you’ll learn what
those function do and this will give you an even better understanding of what is
Doing this exercise also forces you to make you see if you really use that feature or not. I ended up removing entire feature from my configuration because they were taking quite some time to load, and was used almost never. Instead I am forcing myself to learn more what I can do with the built-in features first.
All in all, this bankruptcy was the most fun I had to do. I consider myself still in the process but the base is there.
- I learned a lot !
- My Emacs starts in 0.6s against previously in 5s —
emacs -qstarts in about 0.3s so there is still a little bit of room for improvement.
- I discovered / re-discovered a lot of built-in feature
- I started documenting my configuration, see here.
Well, I’ve look into the portable dump feature of Emacs, thanks to Painless Transition
to Portable Dumper. And I am now down to
0.091s for the startup. There is a few gotchas
with portable dump, I’ll try to write about it later.