用 Dumper 提升 Emacs 的启动速度

今天尝试了一下 emacs 的 protable dumper 功能,它把加载的 package 导出到一个外部文件中,然后启动 emacs 时直接 加载这个文件,这样比一个一个 package 的加载速度快很多。lazyload 是延迟到首次调用时才加载 package,这会导致两个问题:

首次调用的延迟很恼人
在首次进入 prog-mode 或者 org-mode 时,停顿很明显。
刚启动 emacs 时响应延迟
一些通过timer或者延迟 after-init-hook 实现的 lazyload 会导致一些包在启动 emacs 后扎堆加载。

protable dumper却可以规避这两个问题,因为在加载 dump-file 后,所有包已经准备就绪。

不过当前 protable dumper 也并不完美:

  1. 比正常启动 emacs 要多出一个导出 dump-file 的过程。
  2. 一些包导出时会出错等等。

所以,我当前的方案是把 protable dumper 作为补充方案,解决 lazyload 的上述两个问题。

1. Config

主要参考了网上的这篇文章:Painless Transition to Portable Dumper 。这篇文章写得很详尽,把配置思路和踩的一些坑都说的很清楚。下面的内容只是它的一个简述和总结。

1.1. 定制需要 dump 的包

有两类包是我需要dump的:

  • 首次加载延迟很久的包
  • 启动emacs马上需要用到的包

Emacs 提供了 dump-emacs-portable 函数把当前已经加载的包导出到 dump-file。为了只导出特定的包,可以单独提供一个为 dump 所需的配置文件,然后执行下面命令导出 dump-file:

emacs --batch -q -l dump.el

dump.el 中只加载特定的 package,然后调用 dump-emacs-portable 函数。

(require 'package)
(package-initialize)
(setq yx/dumped-load-path load-path
      yx/dumped t)
(dolist (package
         '(elec-pair
           savehist
           winner
           flyspell
           flymake
           eglot
           use-package
           ;; evil
           evil
           evil-owl
           evil-mc
           evil-escape
           evil-surround
           evil-matchit
           evil-visualstar
           vimish-fold
           evil-vimish-fold
           ef-themes))
  (require package))
;; pre-load themes
(load-theme 'ef-duo-light t t)
;; dump image
(dump-emacs-portable (expand-file-name "emacs.pdmp" user-emacs-directory))

1.2. 加载 dump-file 启动 emacs

Emacs 提供了 --dump-file 命令行参数,用来在启动 emacs 加载制定 dump-file:

emacs --dump-file="/User/yx/.emaorg-super-agenda cs.d/emacs.pdmp"

为了不影响 emacs 的正常启动方式,即执行 emacs 命令仍按之前的方式启动,需要在 init.el 文件中添加dump-file启动的条件分支。在上面的 dump.el 中添加了 yx/dumped 变量,并且设置为 t ,这样在导出的dump-file中也会有这个变量,然后在启动过程中就能通过判断这个变量来判断启动方式。下面是 init.el 中的判断逻辑:

(if yx/dumped
    (dumped-run)
  (normal-run)
  )

1.3. Protable-dumper的一些问题

  • 一些包导出报错(global-undo-tree, org-super-agenda )
  • 一些默认模式没有启动(transient-mark-mode, global-font-lock-mode)
  • --dump-file 后的路径名中不能使用 ~
  • scratch buffer 有点异常

这些问题在Painless Transition to Portable Dumper 都有解决。

2. 结语

由于之前的配置几乎都是懒加载的,启动速度已经在 0.7 ~ 0.8 左右了,加上 dumper 后速度稍微变慢了一点,在 0.85 左右。不过整个使用过程比以前丝滑了不少。

最后再说说自己使用中一个不好的感受吧:

每次添加 package 后都要 dump 一次,很麻烦,而且性能提升感受并不明显。 想了一些改进的办法

  1. 隔一段时间 dump 一次,不要每次添加软件都 dump
  2. 坚持只 dump 启动延时很高的 package

Created with Emacs 29.4 (Org mode 9.6.15) by YangXue
Updated: 2025-01-15 Wed 03:54