Subject: bug#4287: reducing emacs size by more frequent garbage-collect calls in loadup.el

From: Dan Nicolaescu <[email-masked]>
Date: Sat, 29 Aug 2009 23:09:10 -0700 (PDT)

Stefan Monnier <[email-masked]> writes:

  > > As the Subject says, replacing each `load' line in loadup.el with 
  > > `load' + `garbage-collect' will reduce the size of the stripped emacs
  > > binary: (.7 is before, .8 is after the change)
  > 
  > > $ ls -l emacs-23.1.50.8 emacs-23.1.50.7
  > > -rwx------ 1 dann dann 6722788 Jul 24 14:20 emacs-23.1.50.8*
  > > -rwx------ 1 dann dann 6857956 Jul 24 14:20 emacs-23.1.50.7*
  > 
  > > $ size  emacs-23.1.50.8 emacs-23.1.50.7
  > >    text    data     bss     dec     hex filename
  > > 1883659 4833256       0 6716915  667df3 emacs-23.1.50.8
  > > 1883659 4968424       0 6852083  688df3 emacs-23.1.50.7
  > 
  > > so we get about 2% reduction by doing something very simple and safe... 
  > 
  > > [This happens because loading multiple files generate more garbage that
  > > can be collected, but it is not returned to the OS, so it appears in
  > > the dumped image].
  > 
  > > See the discussion on this topic on emacs-devel:
  > > http://permalink.gmane.org/gmane.emacs.devel/113176
  > 
  > Can you show the patch?

Sure:

--- loadup.el.~1.180.~	2009-08-20 23:31:53.000000000 -0700
+++ loadup.el	2009-08-29 23:02:34.000000000 -0700
@@ -57,30 +57,49 @@
 (setq buffer-undo-list t)
 
 (load "emacs-lisp/byte-run")
+(garbage-collect)
 (load "emacs-lisp/backquote")
+(garbage-collect)
 (load "subr")
+(garbage-collect)
 
 ;; We specify .el in case someone compiled version.el by mistake.
 (load "version.el")
+(garbage-collect)
 
 (load "widget")
+(garbage-collect)
 (load "custom")
+(garbage-collect)
 (load "emacs-lisp/map-ynp")
+(garbage-collect)
 (load "cus-start")
+(garbage-collect)
 (load "international/mule")
+(garbage-collect)
 (load "international/mule-conf.el") ;Don't get confused if someone compiled this by mistake.
+(garbage-collect)
 (load "env")
+(garbage-collect)
 (load "format")
+(garbage-collect)
 (load "bindings")
+(garbage-collect)
 (setq load-source-file-function 'load-with-code-conversion)
 (load "files")
+(garbage-collect)
 
 (load "cus-face")
+(garbage-collect)
 (load "faces")  ; after here, `defface' may be used.
+(garbage-collect)
 (load "minibuffer")
+(garbage-collect)
 
 (load "button")
+(garbage-collect)
 (load "startup")
+(garbage-collect)
 
 (message "Lists of integers (garbage collection statistics) are normal output")
 (message "while building Emacs; they do not indicate a problem.")
@@ -94,133 +113,220 @@
 
 (message "%s" (garbage-collect))
 (load "abbrev")         ;lisp-mode.el and simple.el use define-abbrev-table.
+(garbage-collect)
 (load "simple")
+(garbage-collect)
 
 (load "help")
+(garbage-collect)
 
 (load "jka-cmpr-hook")
+(garbage-collect)
 (load "epa-hook")
+(garbage-collect)
 ;; Any Emacs Lisp source file (*.el) loaded here after can contain
 ;; multilingual text.
 (load "international/mule-cmds")
+(garbage-collect)
 (load "case-table")
+(garbage-collect)
 (load "international/characters")
+(garbage-collect)
 (load "composite")
+(garbage-collect)
 ;; This file doesn't exist when building Emacs from CVS.  It is
 ;; generated just after temacs is build.
 (load "international/charprop.el" t)
+(garbage-collect)
 
 ;; Load language-specific files.
 (load "language/chinese")
+(garbage-collect)
 (load "language/cyrillic")
+(garbage-collect)
 (load "language/indian")
+(garbage-collect)
 (load "language/sinhala")
+(garbage-collect)
 (load "language/english")
+(garbage-collect)
 (load "language/ethiopic")
+(garbage-collect)
 (load "language/european")
+(garbage-collect)
 (load "language/czech")
+(garbage-collect)
 (load "language/slovak")
+(garbage-collect)
 (load "language/romanian")
+(garbage-collect)
 (load "language/greek")
+(garbage-collect)
 (load "language/hebrew")
+(garbage-collect)
 (load "language/japanese")
+(garbage-collect)
 (load "language/korean")
+(garbage-collect)
 (load "language/lao")
+(garbage-collect)
 (load "language/tai-viet")
+(garbage-collect)
 (load "language/thai")
+(garbage-collect)
 (load "language/tibetan")
+(garbage-collect)
 (load "language/vietnamese")
+(garbage-collect)
 (load "language/misc-lang")
+(garbage-collect)
 (load "language/utf-8-lang")
+(garbage-collect)
 (load "language/georgian")
+(garbage-collect)
 (load "language/khmer")
+(garbage-collect)
 (load "language/burmese")
+(garbage-collect)
 (load "language/cham")
+(garbage-collect)
 
 (load "indent")
+(garbage-collect)
 (load "window")
+(garbage-collect)
 (load "frame")
+(garbage-collect)
 (load "term/tty-colors")
+(garbage-collect)
 (load "font-core")
+(garbage-collect)
 ;; facemenu must be loaded before font-lock, because `facemenu-keymap'
 ;; needs to be defined when font-lock is loaded.
 (load "facemenu")
+(garbage-collect)
 (load "emacs-lisp/syntax")
+(garbage-collect)
 (load "font-lock")
+(garbage-collect)
 (load "jit-lock")
+(garbage-collect)
 
 (if (fboundp 'track-mouse)
     (progn
       (load "mouse")
+      (garbage-collect)
       (and (boundp 'x-toolkit-scroll-bars)
-	   (load "scroll-bar"))
-      (load "select")))
+	   (load "scroll-bar")
+	   (garbage-collect))
+      (load "select")
+      (garbage-collect)))
 (load "emacs-lisp/timer")
+(garbage-collect)
 (load "isearch")
+(garbage-collect)
 (load "rfn-eshadow")
+(garbage-collect)
 
 (message "%s" (garbage-collect))
 (load "menu-bar")
+(garbage-collect)
 (load "paths.el")  ;Don't get confused if someone compiled paths by mistake.
+(garbage-collect)
 (load "emacs-lisp/lisp")
+(garbage-collect)
 (load "textmodes/page")
+(garbage-collect)
 (load "register")
+(garbage-collect)
 (load "textmodes/paragraphs")
+(garbage-collect)
 (load "emacs-lisp/lisp-mode")
+(garbage-collect)
 (load "textmodes/text-mode")
+(garbage-collect)
 (load "textmodes/fill")
 (message "%s" (garbage-collect))
 
 (load "replace")
+(garbage-collect)
 (load "buff-menu")
+(garbage-collect)
 
 (if (fboundp 'x-create-frame)
     (progn
       (load "fringe")
+      (garbage-collect)
       (load "image")
+      (garbage-collect)
       (load "international/fontset")
+      (garbage-collect)
       (load "dnd")
+      (garbage-collect)
       (load "mwheel")
-      (load "tool-bar")))
+      (garbage-collect)
+      (load "tool-bar")
+      (garbage-collect)))
 (if (featurep 'x)
     (progn
       (load "x-dnd")
+      (garbage-collect)
       (load "term/common-win")
-      (load "term/x-win")))
+      (garbage-collect)
+      (load "term/x-win")
+      (garbage-collect)))
 
 (message "%s" (garbage-collect))
 
 (if (eq system-type 'windows-nt)
     (progn
       (load "w32-vars")
+      (garbage-collect)
       (load "term/common-win")
+      (garbage-collect)
       (load "term/w32-win")
+      (garbage-collect)
       (load "ls-lisp")
+      (garbage-collect)
       (load "disp-table")
+      (garbage-collect)
       (load "dos-w32")
-      (load "w32-fns")))
+      (garbage-collect)
+      (load "w32-fns")
+      (garbage-collect)))
 (if (eq system-type 'ms-dos)
     (progn
       (load "dos-w32")
+      (garbage-collect)
       (load "dos-fns")
+      (garbage-collect)
       (load "dos-vars")
+      (garbage-collect)
       ;; Don't load term/common-win: it isn't appropriate for the `pc'
       ;; ``window system'', which generally behaves like a terminal.
       (load "term/pc-win")
+      (garbage-collect)
       (load "ls-lisp")
-      (load "disp-table"))) ; needed to setup ibm-pc char set, see internal.el
+      (garbage-collect)
+      (load "disp-table")
+      (garbage-collect))) ; needed to setup ibm-pc char set, see internal.el
 (if (featurep 'ns)
     (progn
       (load "emacs-lisp/easymenu")  ;; for platform-related menu adjustments
-      (load "term/ns-win")))
+      (garbage-collect)
+      (load "term/ns-win")
+      (garbage-collect)))
 (if (fboundp 'atan)	; preload some constants and
     (progn		; floating pt. functions if we have float support.
-      (load "emacs-lisp/float-sup")))
+      (load "emacs-lisp/float-sup")
+      (garbage-collect)))
 (message "%s" (garbage-collect))
 
 (load "vc-hooks")
+(garbage-collect)
 (load "ediff-hook")
-(if (fboundp 'x-show-tip) (load "tooltip"))
+(garbage-collect)
+(if (fboundp 'x-show-tip) (progn (load "tooltip") (garbage-collect)))
 
 (message "%s" (garbage-collect))