Emacs Start-Up: Speeding It Up
1 TL;DR:
Describes my Emacs start-up file, and what I did to speed it up from
12 seconds to under 4 seconds.
2 Overview Of Steps
- Byte-compile start-up files.
- Temporarily increase gc-cons-threshold during startup.
- Load package autoloads (not packages) during start-up.
- Use eval-after-load to advantage for post-package setup.
- Lexically bind file-name-handler-alist to nil if start-up
is split across many files. - Used memoization to avoid network lookup of current location during startup.
I have a large number of elpa/melpa packages installed:
(length load-path)
400
With the above, my emacs (Emacs 26 built from Git) startup time is on
average 4 seconds. This includes starting up emacspeak (including
speech servers), as well as launching a number of project-specific
shell buffers. Given that I rarely restart Emacs, the startup time is
academic — but speeding up Emacs startup did get me to clean-up my
Emacs setup.
3 Introduction
I have now used Emacs for more than 25 years, and my Emacs start-up
file has followed the same structure through this time.
- The init file defines a
start-up-emacs
function that does the
bulk of the work. - Package-specific configuration is split up into
<package>-prepare.el
files. - All of these files are byte-compiled.
As a first step, I added code to my start-up file to time the loading
of various modules.
4 Load Byte-Compiled Start-Up File
I keep my emacs-startup.el
checked into GitHub.
My Emacs init-file is a symlink to the byte-compiled version of the
above — this is something that goes back to my time as a
grad-student at Cornell (when GitHub of course did not exist).
That is also when I originally learnt the trick of temporarily setting
gc-cons-threshold to 8MB — Emacs' default is 800K.
5 Package Autoloads And eval-after-load
Over time, some of the package-specific setup files had come to
directly load packages — it just made it easier to do
package-specific setup at the time. As part of the cleanup, I updated
these to strictly load package-autoload files and wrapped post-package
setup code in eval-after-load
— this is effectively the same as
using use-package
.
6 Loading Files Faster
Emacs has an extremely flexible mechanism for loading files — this
means you can load compressed, encrypted or remote files without
having to worry about it. That flexibility comes at a cost — if you
are sure you dont need this flexibility during start-up, then locally
binding file-name-handler-alist
to nil
is a big win — in my
case, it sped things up by 50%.
7 Avoid Network Calls During Start-Up
In my case, I set calendar-latitude
and calendar-longitude
by
geocoding my address — geocoding is done by calling the Google Maps
API. The geocoding API is plenty fast that you normally dont notice
it — but it was adding anywhere from 1–3 seconds during
startup. Since my address doesn't change that often, I updated module
gmaps to use a memoized version. My address is set via Customize
,
and the geocoded lat/long is saved to disk automatically.
8 References
- Emacs Speed What got it all started.
- file-name-handler-alist The article that gave me the most useful
tip of them all.
Net