82 comments

[ 2.5 ms ] story [ 145 ms ] thread
Completely unproductive comment teasing an old pointless flame war.
(Despite the comment clearly being flamewar bait...)

Most of the other comments are correctly suggesting to just not exit emacs. Something opening slowly once at the beginning of a long workflow is hardly an issue. If you must open something quickly over and over again, being proficient in a secondary lightweight editor like vim wouldn't be a bad suggestion.

Easiest thing is just not to quit!

I stopped autoloading things, as i found it less bothersome to wait 30 seconds for Emacs to load than to get surprised by an autoload delay while working.

Sadly my emacs freezes about once every 2 weeks. Hand rolled config that restores everything within 30 seconds. But still.
My Emacs takes ages to start but for a reason. It takes most of the time to automatically load every file I've ever edited into a buffer. Finding the right buffer is much faster for me than navigating the filesystem, and whenever I use bookmarks they're outdated too quickly or I can't remember them. I guess my habit is the equivalent of piling papers on a desk.
I just use recentf for that. My buffer list contains everything in the recentf (this works with buffer list replacements from both Helm and Ivy). Makes it trivial to open up any file I've had open before.

Opening all buffers you've ever edited sounds nuts to me. What if one of the files you edited was a 10 gb log file or whatever?

I like this approach and almost considered doing it after reading this - or probably only opening the last few hundred files - but then I realized that the recent file list probably gets me 99% of the way there. Is there anything you get by opening the files that you wouldn't get by opening files from the recent file list instead?
well I usually have trouble remembering the exact name of the file I was editing 2 months ago? :) . Now if there is a plugin to have rg look through the last few hundred files that I've edited that would be a game changer.
I have something very much like this, a trivial addition to find-file. Typing C-u C-x C-f shows the recently edited filenames (with paths), and vertico + orderless makes it a joy to instantly pick the specific recent file. I get the same UI with regular find-file (C-x C-f), so the two bindings live harmoniously in my brain and fingers.

    (defun MY-consult-find-file (arg)
      "If no prefix: find-file, otherwise consult-recentf."
      (interactive "p")
      (let* ((filename
              (if (eq arg 1)
                  (call-interactively 'find-file)
                (call-interactively 'consult-recent-file)))
             )))

    (global-set-key (kbd "C-x C-f") 'MY-consult-find-file)
Before switching to vertico/orderless, I used ivy with essentially the same machinery. That worked great too.
I find 'ido-use-virtual-buffers' a much more lightweight way of achieving this, FWIW. I'm sure similar features are available for Ido alternatives.
While I’m very much in the “don’t really care” camp cos I don’t quit Emacs often, I did find optimising my startup time quite educational, and moving to use-package gave me an opportunity to go through every mode in detail, instead of just making the occasional ad-hoc tweak when something annoyed me.

I would also point out that early-init exists these days and is the best place for some startup logic (especially bits that prevent UI ever being shown so you don’t get weird flashes of stuff during startup).

Ideally use-package would simply be included in emacs, so you could rely on it.

Apparently they are getting close: https://github.com/jwiegley/use-package/issues/282

Until then, I have this in my init.el to install it if necessary:

    ;; Install use-package because that installs everything else
    (unless (package-installed-p 'use-package)
      (package-refresh-contents)
      (package-install 'use-package))

    (require 'use-package)
except that use-package, by itself, does not install anything.

  NOTE: use-package is not a package manager! Although use-package does have the useful capability to interface with package managers (see below), its primary purpose is for the configuration and loading of packages.
(I use straight, which interfaces nicely into use-package.)
> except that use-package, by itself, does not install anything.

It can be configured to install things (by using the builtin package.el): https://jwiegley.github.io/use-package/keywords/#ensure-pin

> You can use use-package to load packages from ELPA with package.el. This is particularly useful if you share your .emacs among several machines; the relevant packages are downloaded automatically once declared in your .emacs. The :ensure keyword causes the package(s) to be installed automatically if not already present on your system (set (setq use-package-always-ensure t) if you wish this behavior to be global for all packages)

So if all you need is package.el (and there's a good chance that's the case), you can just

    (setq use-package-always-ensure t)
and your configuration will now install the packages if you copy it to a new system.
I do what the author mentions as the common retort to their approach: starting an Emacs daemon (server) at boot, and opening Emacsclient when needed. In general, I always have one frame open to do actual work on, but the client is still useful if I ever navigate with a file explorer or open things through the command line (all text extensions open in Emacs).

I'm not sure all the extra effort needed really does the trick - I don't think mine would start up 'fast enough' to beat running a daemon even if I deferred loading most of my config (which can lead to config issues at times).

That being said, I had a look at their dotfiles, and it seems really well organized. If such an effort makes you write a great config, it may be worth it regardless of whether you end up using the daemon or not!

I prefer having a clean instance so I can open up an emacs for the project I'm currently working on, as opposed to lugging all those other buffers around and leaving any changes intact. So I don't use a daemon.

And these "advanced techniques" aren't really all that hard - 90% is just using use-package, which has a number of other advantages. It can be set up to install uninstalled packages, so you can do a self-installing init.el. In my case mine will download my other config files, install use-package and then install all packages I use.

It also leads to better organization of your config, because you keep the packages self-contained instead of splattering random settings all over init.el.

I no longer let use-package install things. I use the same init on different computers, so sometimes I would have to wait for use-package to install things on startup and sometimes melpa would be down or some package would be a newer version and require new deps and use-package doesn't handle such situations. It's very little gain for a lot of hassle. Instead I just check all of emacs.d/elpa into the same git repo. That way I can also easily review changes or roll back to last working version.
I tried this for a while but got sick of dealing with byte compilation issues. Different versions of Emacs on different systems, occasional mtime skew especially if switching branches but sometimes I think just an unlucky clock tick.
I use use-package with nix but disable package.el being able to install anything.

This way I get fast startup and the download problem you mention doesn't happen.

If nix isn't your thing, I used to do the same with straight.el by checking in .emacs.d/straight and disabling install by setting repos to nil.

>lugging all those other buffers around

project(ile)-switch-to-buffer is your friend.

Here's mine: https://wiki.archlinux.org/title/emacs#As_a_systemd_unit

and aliases

   ec='emacsclient -nc'
   e='emacsclient -c'
I still use neovim because sometimes it's neater that the file opens up in the same terminal where I am in.
You can instruct Emacs (with or without emacsclient) to open in a terminal with:

   emacsclient -nw
That way, you'll connect to your Emacs server but using a terminal Emacs (even if your main instance is GUI Emacs)
Oh, I wonder how I had missed that option. Thanks!
or you use vterm-mode as your terminal and then you simply open a file like you do now, except now it opens in place of the vterm-mode buffer. Close the buffer like you would do, and you're back to vterm.
I’d like to see something like this but for speeding up Emacs at runtime. I have a 0.25s startup time with packages but my Emacs struggles when using lsp-mode or eglot in large C++ projects. I’ve been using Sublime Text lately but would like to get back to Emacs.
Is it Emacs, or the language server? It would be interesting to profile.
Eight Megabytes And Constantly Swapping :)
I was searching the comments for this!

I used my first Unix machine in 1991 and started college in 1993. I knew vi but the professor used emacs and showed us how to run make from within emacs. But wow was it slow! I asked an older student and he said EMACS was just like GNU and was a recursive acronym. Emacs Makes A Computer Slow and then told us Eight Megs And Constantly Swapping. The workstations had 16MB RAM at the time. One big problem was that vi was installed locally on every machine while Emacs was on a remote file server and there were probably 50 students typing "emacs" at the same time at the start of class all accessing the same server.

I just used vi and a bunch of terminals although later I used XEmacs in "viper" mode (vi keybindings) because it had color syntax highlighting and the split window support was cool. Vim got those features a long time ago so I just keep using vi/vim

Ha! I was just thinking about that acronym. I guess the whole point of all this new hardware compute power on Apple Silicon and TSMC processes is to run emacs faster...
I gave up on Emacs and went back to Vim because of the slowness and the bugs I was encountering while using the Emacs GUI (granted a lot of them were from lsp-mode and other heavy packages). While digging for answers I was told not to use certain platforms, don't use the GUI, use the GUI, don't turn Emacs off etc. which felt like Stockholm syndrome to me. There's a lot of cargo culted config fragments like the ones you'll find in the article. Why does every user have to constantly reinvent the same config to work around all of the issues in Emacs? I don't know, but I wasn't going to stick around and find out. Vim with all of my plugins, which has the same features as my Emacs config, starts up instantly and I've yet to encounter a single bug. I really wanted to like Emacs, and I've chalked up my bad experience to less people putting dev time towards it rather than actual negligence towards the user experience. In the article the author talks about how he's gone bankrupt three times with his config, maybe that's a sign that the problem isn't the author. If Emacs is that fragile, then its extensibility is really a moot point.
Yeah, as soon as you start customizing emacs (which is the whole point of emacs), you run into bugs. Everything is always slightly broken all the time; I don't think it's actually humanly possible to fix this -- too many parts. Fix one thing, another thing breaks.

I'm addicted to the flexibility, but I dream of something that offers the same level of flexibility in a more robust ecosystem (e.g. statically typed, statically scoped, what else?). (Is such a thing even possible? I don't know!)

>Everything is always slightly broken all the time; I don't think it's actually humanly possible to fix this -- too many parts. Fix one thing, another thing breaks.

Speak for yourself. Just last weekend I had a few hours with little to do, and actually wanted to do some yak shaving on my Emacs config just for the hell of it. but it works too well and I have everything the way I like it! My yak is f*kin' bald, man!

Not only have I already worked out all the little bugs that annoy me, but I've added all the features I can think of that I want!

Well, I'm jealous!

Here's my list of problems to solve on a rainy day†:

    ;; * kill-word-sp cancels ioccur mode for some reason
    ;; * after running ipython for a while, all terminal commands hang waiting for output
    ;; * iedit substition starts just corrupting shit (e.g., try replacing \t with spaces)
    ;; * "replace-match-maybe-edit: Match data clobbered by buffer modification hooks"
    ;; * delete-horizontal-space doesn't work w/ iedit mode
    ;; * vc-annotate doesn't properly restore window configuration
    ;; * the popup used by dumb-jump breaks when line wrapping is enabled and it's used on a wrapped line
    ;; * sometimes trying to launch a new shell just kills the old shell
    ;; * godef doesn't work when narrowed
    ;; * emacs stopped automatically recompiling .emacs wtf
    ;; * grep-ed while buffer is in loccur mode fucks things up
    ;; * undo in loccur mode messes things up
    ;; * visual-line-mode jumps around on very long lines (like paragraph long)
    ;; * parens don't overwrite properly in go-mode
    ;; * «Error running timer `auto-revert-buffers': (wrong-type-argument number-or-marker-p nil)»
    ;; * shell doesn't save history a lot of the time
    ;; * piece of shit grep edit silently fails on spaces on file names
    ;; * code-wrap is stupid with long separator lines (like "//---" for a long time)
    ;;   - sadly might be a visual line mode bug, actually...
    ;; * line highlight doesn't work after jumping to a definition
    ;; * highlight line mode doesn't work on most recent line in shell
    ;; * tendency to identify buffers by name causes bugs when renaming buffers ("stringly typed")
    ;; * subword mode doesn't think DEBUG_MEGA_GOLD is three words (in a .go file)
    ;; * if a shell command tries to open a file in emacs, and the active window is the minibuffer, the file will open into the minibuffer
Probably the biggest source of issues is two different modes not playing well with each other, which is understandable, but also something it feels like a less freeform approach to an editor might reasonably be able to do a better job of avoiding.

† To be fair, not all bugs -- some are just configuration issues I haven't figured out yet.

> ;; * emacs stopped automatically recompiling .emacs wtf

Change to follow XDG specification and ~/.config/emacs having precedence?

Not sure what that means, but I appreciate the response!

It's been a while since I wrote that note to myself, but I somehow had .emacs setup so it'd get recompiled automatically to byte code on changes (which helps startup speed), and somehow whatever I setup at some point stopped working. (Which resulted in my .emacs changes being silently ignored, as stale .elc was used -- that was confusing to figure out!)

For now I just gave up and stopped using the byte-compiled version, sometimes life is too short, even for an emacs user!

(Though in general anyone who chooses to use emacs must not think life is TOO short...)

> Yeah, as soon as you start customizing emacs (which is the whole point of emacs), you run into bugs. Everything is always slightly broken all the time; I don't think it's actually humanly possible to fix this -- too many parts. Fix one thing, another thing breaks.

There's no difference between an advanced emacs config and a software project.

If you don't test or incubate features long enough before your workflow depends on them you'll find yourself building atop more bugs.

I find tagging releases of my emacs config useful for this.

For sure. But I think what's going wrong is a little different.

E.g., there's a mode that highlights the current line. And there's a mode that let's you run a shell inside a buffer.

And for some reason, the current line highlight doesn't work on the most-recent (waiting for input) line.

OK, actually looking at this a little more closely, I think it's because shell mode does some sort of thing where it redefines the "start" of the line to not include the shell prompt, and I guess whatever is doing the line highlighting is using that same notion of "start" of line. So on a line that just contains the prompt, the line highlighter thinks the line is zero length, and highlights nothing.

I think this is typical of lots of emacs problems. You have all these modes that interact w/ each other, w/o strong models of the interactions, so you end up with a bunch of little bugs.

(And because there's combinatorially many different ways you can combine modes, I don't think testing is ever really going to help you here. You just need formal structures and coding styles that guarantee or lend themselves more to correctness.)

My init files are nearly 10k lines and I have >300 packages. I've never "declared .emacs bankruptcy." Emacs starts in 0.4-0.6 seconds (without the daemon) for me. One reason I initially switched to Emacs was because Vim was comparably slow as hell for what I was doing. That's no longer the case. Neovim and Vim are definitely faster than Emacs, but I almost never run into cases where it matters. Even on my crappy work laptop, the only time I ran into issues with Emacs is when dealing with log files that were gigabytes (in cases like that evil's :g and :s are just unusably slow).

> There's a lot of cargo culted config fragments like the ones you'll find in the article.

Besides changing the gc-cons-threshold (which is indeed a questionable fragment to blindly copy/paste), there were no other specific config fragments, only examples. People blindly paste config fragments for everything (e.g. set nocompatible in Vim).

> Why does every user have to constantly reinvent the same config to work around all of the issues in Emacs?

What is there to reinvent? It should take almost no extra configuration to properly defer package loading. Package loading is also not automatic. If you are explicitly loading every package you've installed during init, that's your fault. You shouldn't blindly copy things into your config. If you really don't want to handle configuration yourself, starter kits exist for a reason.

> In the article the author talks about how he's gone bankrupt three times with his config, maybe that's a sign that the problem isn't the author. If Emacs is that fragile, then its extensibility is really a moot point.

It is mostly a user problem. Emacs lets you do anything. It gives you enough rope to hang yourself with. I could write an unreadable and broken mess of a program in any programming language, but that doesn't say anything about whether a language is fundamentally flawed.

It's a double-edged sword. There's no such thing as bug-free software. And the more functionality, the more room for misconfiguration and bugs. Vim/neovim come nowhere close in terms of functionality. The correct word isn't "fragile." A better word would be "malleable." It's the editable editor. Emacs' malleability is at least part of the reason why it's able to stay relevant despite the fact that it has very few developers compared to Vim and other editors. Because Emacs is this way, it's potentially easier to do something dumb or install a bunch of useless, slow packages, but because Emacs is this way we also have Magit, org-mode, and a bunch of other killer packages that Vim has much worse versions of (or no equivalent of at all).

This means that if you only need a simple setup, Emacs is not that appealing, but my experience has been that I have no idea what I want until I know what is actually possible (e.g. I didn't grok magit until I read the entire manual and saw how greatly it would simplify my workflow).

Good Tips ! :)

Just thought I'd add a side-note;

For anyone wanting to try emacs really give "Doom Emacs" a try ! It's brilliant and comes with vim-bindings (a.k.a evil-mode) !

Doom Emacs has spend a lot of time on making emacs(doom) fast !

This post felt like a deja vu, because I had read this earlier back in Nov 2017 :). The HN mods should add the 2017 year to the title. That said, for people who haven't read this post earlier, this post shares some great tips! I like the one about deferring packages using `use-package`.

Because this is an old post, references like Spacemacs are now quite dated. Folks prefer Doom Emacs nowadays (though I don't use either of them).

I honestly don't understand the point.

Emacs (much like VSCode or Idea) is a tool that I use for everything, all day. I don't see a point in shutting it down, except for upgrading the version. Its startup time of, say, 15 or even 30 seconds (if you start many language servers) is only paid once, when I log in.

So I run it in server mode, and emacsclient start instantly, as a GUI window, or in a terminal, with all the amenities of an IDE already in place.

Just different use cases then. Emacs isn't my main coding tool these days but I still use it for single-file editing, and I close it when I'm done with that file. The start up time does matter to me somewhat. Though I have a pretty simple config for the same reason and it's not bad enough for me to spend time on. I do keep an eye on it though.
Use the emacs server then. Start once use many.
"emacs --daemon" and emacs-client are key to solving this scenario
I hope this doesn't come along as aggressive but:

Do you really have a "different use case", or are you just averse to the idea of running it in the background as a daemon? Do you really need to save the 70 MB (without addons) to 200 MB (with addons) that it takes sitting there?

Unlike bloated Electron apps, Emacs doesn't actually use CPU while you're not using it - it just sits there, takes up a little memory (and even on my old 4 GB RAM ThinkPad it's not enough to actually inconvenience me), and awaits you opening a new frame with emacsclient.

I don't know I'm not an "emacs guy" really, I didn't know about this feature. It will probably work for me and I'll consider setting it up the next time I twiddle with my emacs config, something I do for an hour or two about once a year.

But whether or not it solves my problem yes I think the use case is different? The person I responded to uses it so consistently they leave it running at all times. I can go days or weeks between single uses, depending on the projects I'm working on. That's a very different use to me.

Ah, well, if you're going days/weeks between using it, then I understand why it wouldn't be useful for you to figure out how to configurate it more, and why leaving it running in the background would be mostly a waste. That makes sense.

Although, now, I'm sure that many of us are curious - why would you only use Emacs this infrequently, but bother to use it at all?

I used to use it a lot and do prefer it in the abstract. Just, my daily work has shifted to where I spend a lot more time exploring unfamiliar codebases, making small changes and refactors, and pairing in them. I work in a lot of different languages. Maintaining an emacs config that is truly very good at everything started to feel like a part time job on its own.

Plus I work remote and for better or worse vs code has become conventional for remote pairing. So I have a minimal emacs config for when I don't need any particular language integration, and the rest of the time vs code is good enough for the daily work I actually do, which is rarely writing out features from scratch anymore.

> Its startup time of, say, 15 or even 30 seconds

Jesus. I use Gvim, which starts in less than a second. When I'm done editing, I close it. The only app I generally leave open, is browser. How people can justify such awful performance is beyond me, and why I will never, ever use Emacs.

While it can be very slow it's not something I even notice. When I start my computer, the terminal also starts on login, which means emacs starts. By the time I am ready to use it it loads instantly.
How much code intelligence does GVim give you? Code navigation? Type information? Refactoring?

The question is actually about IDE features which take longer time to initialize, mostly in the non-Emacs code such as language servers.

Emacs with only built-in plugins loads from scratch instantly on my machine. But if I only need to do a simple quick edit, I can equally invoke vi :) (Which I regularly do, to keep my basic vi skills current.)

Looks like you're judging a fish by it's ability to climb a tree.
Said like such a vimmer. Anyway, my real comment is that I used vim exclusively for 5 years before switching to Emacs for like the past 9. I use evil mode to emulate vim of course. I'd run a server and ZZ or :wq as soon as I finished editing the file. My colleague, a regular Emacs user, commented how I drive emacs like vim in pair-coding.

Now with vterm I run Emacs all the time, my buffers stay mostly open. Anyway, the best manner to use the tool is probably dictated by the tool, but I will tell you I am not bothered at all for my Doom Emacs 2 second starting time every few hours / days.

For Emacs to start that slow they probably load a ton of packages if not a framework like Spacemacs. If you just load simple settings, it opens instantly.
If it's taking 15 seconds to start, it's because the person is doing things with it that Gvim can't do. An empty config probably takes 1s to load.

It's like complaining that it takes 30s to boot your PC when Gvim opens up instantly. It's a silly comparison.

I mean 90% of the problem is overcome just by running emacs server.
(comment deleted)
I just disable emacs garbage collection entirely. Fast startup, no more random pauses, haven't noticed any problems yet. (This was probably like a year ago.)

(On the other hand, emacs is never quite problem free, so maybe this is introducing problems and I just haven't noticed.)

I have tons of customizations and lots of packages, but be as religious as reasonable about lazy loading.

    $ time emacs --eval '(save-buffers-kill-emacs)'
    real 0.21s
Not bad, but still very noticable, which is annoying.

About half of it is unavoidable.

    $ time emacs -q --eval '(save-buffers-kill-emacs)'            
    real 0.11s
(-q disables reading the config file.)

(With default GC settings, startup is about 300ms.)

Instead of totally killing the garbage collector, you can effectively turn it off during startup by setting gc-cons-threshold to a large number, and then restore it after init. The article touches on this but they don't increase it very much and restore it at the end of init.el (emacs-startup-hook runs later).

early-init.el:

  (setq gc-cons-threshold most-positive-fixnum)
  (add-hook 'emacs-startup-hook (lambda ()
    (setq gc-cons-threshold (* 2 1024 1024))))
It was subtle in my message, but my other reason for disabling was to avoid random collection pauses when using emacs.

A sibling poster recommended GCing on deactivate, which is an interesting idea!

But again, I truly haven't been able to notice any ill effects of not GCing. I tend to probably leave emacs open for maybe a few hours at a time, so I guess in that sense I'm manually GCing. :-)

Not running the GC at all is certainly interesting though :)

Have you tried running 'M-x memory-report' before quitting to see how much memory you ended up using?

My emacs ain't new enough to have memory-report. I tried just running memory-report.el from HEAD, but it errored out (after hanging emacs for like 3 mins!).

Anyway, here's the poor man's version:

cons-cells-consed is 38315202

There's probably some roughly accurate map from that to number of bytes of memory allocated, I will take a totally random guess it's 10, which would give 383MB of memory used.

I'm at half a day of usage, so figure 800MB by end of day. 16GB machine, so you can see why my "garbage collect once a day before bed" strategy is working out ;-).

(Plus also I wonder how much of the uncollected garbage just gets paged out by the OS and never touched again.)

I like to do this to ensure GC happens occasionally, when I focus away from Emacs:

    (add-function :after
                  after-focus-change-function
                  (lambda () (unless (frame-focus-state)
                               (garbage-collect))))
Ah, neat idea! Thanks!
Honestly I'll rather prefer a bigger multi-threading/MP usage to reduce deadlocks because Emacs is an ecosystem, even reducing it's startup time to the minimum it will never be like Vim, those who do not use EXWM simply can run Emacs daemon at their desktop startup to much with the client Vim startup time, BUT those who use Emacs as a DE like me I bet all prefer far less freezing like during packages upgrades, feeds fetching, Gnus etc vs the not really relevant startup time...
even with every module and restoring my buffers Emacs loads faster than any other IDE I use.
> Restarting Emacs helps verify that customization will persist between sessions.

On this point I agree, but another (better, in my opinion) option is to hack in one instance and spawn a second to check the config changes you're making. You can kill and recreate the spawned one with less interruption to your work.

From the article, in rebuttal to the "use daemon mode" argument:

> Fast things feel nicer.

Daemon mode is fast. Mine takes less than a second to open a new frame with a fully-loaded Spacemacs setup, and while my startup time is 20-30 seconds, it runs in the background upon login, and I don't care about that gap.

> When customizing Emacs, you sometimes get into weird states that can be hard to recover from without restarting. For example, if you add a slow lambda function to your post-command-hook, it’s tough to remove it.

> Restarting Emacs helps verify that customization will persist between sessions.

These only matter if your primary use-case for Emacs is...customizing Emacs. Which is a thing that some people do, I guess, but I'm more interested in using Emacs as a tool. Sure, I'm going to spend dozens of hours tweaking it, but I'll spend thousands of hours using it - and rewriting my init.el (especially from its current Spacemacs state) is also going to take dozens of hours, which will definitely wipe out any gains that I would have gotten from having a slightly faster iteration time during the elisp development loop.

That said, I still think that the information presented in the article is useful! It's always good to know why software is slow and how to make it faster, and some people just don't want to use daemon mode.

20-30 seconds? I thought VSCode was slow and that only takes about 10 (with lots of heavy extensions).
I’m honestly more excited by helix at this point, though I’m still using emacs with doom and daemon mode setup.

The thing about helix is… it starts instantly and let’s say 90% of what I care about

One of the problems I never knew I had. Made me curious, how long does it actually take to start. Not entirely trivial to determine, but for the initialization time, Emacs has a function which reports it (of course):

  (emacs-init-time)
  "4.7 seconds"
Holy cow, that's a lot. But perhaps given that this is a first gen. Banana Pi (1GHz dual-core ARM32) not actually all that much. And given

  (emacs-uptime)
  "99 days, 3 hours, 14 minutes, 25 seconds"
not significant either.
Author here. Things that have changed since I published this.

- Doom emacs does most (all) of these with a bunch of cleverer techniques than mine. I’d recommend doom over rolling your own emacs.

- I use IntelliJ just about exclusively.

- I now do the minimal amount of customization I can get away with.

(2017) really, but still relevant