16

I added the following two lines to the top of my init.el:

(setq gc-cons-threshold (eval-when-compile (* 1024 1024 1024)))
(run-with-idle-timer 2 t (lambda () (garbage-collect)))

That means that instead of collecting garbage every 800kb of allocated memory, Emacs does so when idle, i.e. when the pausing does not bother me. (It also collects after allocating 1GB of memory, but I don't think that will happen).

This improved my startup time by about two thirds. In theory, it should also improve performance in general. Are there any downsides to this approach?

  • FWIW, I haven't touched the garbage collection settings, and have never been aware of it during normal operations. – Dan Jul 22 '17 at 14:10
  • I re-posted a link to this thread over on reddit/emacs reddit.com/r/emacs/comments/6ow208/… and Eli Z. (a lead developer/maintainer of Emacs) has already posted a comment. There may be additional comments within the next few days. – lawlist Jul 22 '17 at 17:25
  • 1
    In principle you shouldn't set gc-cons-threshold any higher than you're willing to actually hit at any given time, because you ought to assume that you will actually hit that value from time to time (after all, who knows how much garbage might be accrued by some unexpectedly-enthusiastic non-idle task). I don't see a particular problem with triggering gc with an idle timer, but I think setting the threshold for non-idle gc as high as this seems OTT, and my impression is that the value was probably chosen as being "higher than I'll ever need" rather than "the highest I'm willing to use". – phils Jul 24 '17 at 1:28
  • 4
    According to this post by Stefan Monnier: "Better not touch it. In Emacs-22 we introduced gc-cons-percentage which provides the same benefit as increasing gc-cons-threshold but without the drawbacks. And without having to fiddle with it. I.e. I'd recommend users to remove any gc-cons-threshold settings from their .emacs." – izkon Sep 22 '17 at 6:03
  • 1
    @Hi-Angel I don't think that is a good idea. If Emacs actually allocates huge amounts of memory without becoming idle, it should gc instead of continuing to allocate until the system has to swap or even runs out of memory entirely. If anything, 1GB is already too high. – Erik Jul 24 '18 at 13:18
4

As far as I know, if you have the RAM, it's okay, but if Emacs ever did hit really high usage before GC'ing, it might take a long time. I'm not sure exactly what Eli means; ISTM that if you have enough memory, it should be okay, but he's the expert here.

Having said that, I've used these lines in my init file for a while now, and it helps reduce startup time without making the changes permanent:

;;;;; Startup optimizations

;;;;;; Set garbage collection threshold

;; From https://www.reddit.com/r/emacs/comments/3kqt6e/2_easy_little_known_steps_to_speed_up_emacs_start/

(setq gc-cons-threshold-original gc-cons-threshold)
(setq gc-cons-threshold (* 1024 1024 100))

;;;;;; Set file-name-handler-alist

;; Also from https://www.reddit.com/r/emacs/comments/3kqt6e/2_easy_little_known_steps_to_speed_up_emacs_start/

(setq file-name-handler-alist-original file-name-handler-alist)
(setq file-name-handler-alist nil)

;;;;;; Set deferred timer to reset them

(run-with-idle-timer
 5 nil
 (lambda ()
   (setq gc-cons-threshold gc-cons-threshold-original)
   (setq file-name-handler-alist file-name-handler-alist-original)
   (makunbound 'gc-cons-threshold-original)
   (makunbound 'file-name-handler-alist-original)
   (message "gc-cons-threshold and file-name-handler-alist restored")))
  • Why don't you use after-init-hook? – Erik Jul 24 '17 at 23:06
  • 2
    Because that would run immediately after initialization, which might make the user wait for GC. By using an idle timer, it can run when the user's not using Emacs. – blujay Jul 26 '17 at 8:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.