网上流传这么一个段子:emcas启动过程中可以煮一壶咖啡。(程序员在打开emacs的1-2分钟的碎片时间,可以干些什么?)
对于圣战结束后对比过vim和emacs才入坑emacs的我来说,不管是365天开1次emacs,还是1天开365次emacs,都无法忍受emacs比其他同类慢。所以在最近重写init-file的过程中尤其注重各种包的配置对emacs启动时间的影响。
电脑:2016年的macbook,macOS Big Sur 11.5.1
emacs:emacs 27.2 安装方法: brew install emacs-plus --with-no-titlebar --with-modern-vscode-icon
包管理:use-package & straight.el
参考文章:
完全摒弃package.el的配置,用use-package和straight.el管理所有的包
于是,不断的精简配置和结构化配置,不再需要package.el的一堆累述,全部的package通过straight自动从github上下载,melpa没有的包也能通过统一化的配置来安装:
(use-package XX
:straight ....)
为了高度统一,那些build-in的包或者自定义的defualt也由use-package管理,例如:
(use-package frame
:straight (:type built-in)
:hook (before-make-frame-hook . window-divider-mode)
:custom
(window-divider-default-right-width 12)
每添加一组(use-package XX)
配置都会写上“延迟加载”,然后重启一下emacs,看看M-x emacs-init-time
用时多少,尽量避免写了过多配置而不知不觉中拖慢启动时间,尤其是新手抄作业很容易不小心拖慢启动时间。
就我个人环境而言,emacs -Q的时间为0.34-0.35秒
起初,early-init.el 只添加gc垃圾回收相关配置和(setq package-enable-at-startup nil)
,init.el 只添加use-package + straight
初始化配置。这样最精简的配置也增加了0.2秒的时间,总用时0.52左右。后续添加了theme相关的配置,包括对defualt窗口之类的设置,虽然都:hook (window-setup . XX)
了,但还是要花费0.02秒,总用时波动在0.54-0.56秒。
由此可见,即使add-hook了,还是会随着package的增多而增加启动时间,从几毫秒到几十毫秒不等。在不断的add-hook
和大致了解了Emacs 启动过程后,我突发奇想:为何不给整个init.el
从头到脚加一个add-hook
呢?
于是整个init.el
就变成了这样子的:
第二行;;;;;;;;;;;;;;
下面就是各个(use-package XX)
的配置和(add-hook
及(lambda
的两个))
。神奇的事情也随之发生,为了单一对比& emacs -Q
,遂从终端( & emacs
)启动emacs,启动时间瞬间缩小为0.30-0.31秒!
而通过alfred启动emacs,时间还要减少0.01秒左右:
经过多次以不同方式对比启动emacs,发现add-hook init.el
后GUI emacs的启动时间确确实实突破了emacs -Q的时间。理论上emacs -Q的时间是GUI emacs的最快时间,着实惊讶到我了。真!在眨眼的瞬间启动图形化emacs!
总结与疑惑:
1、平时加载一些包会hook在after-init-hook,却不会影响emacs启动时间。从上图得知,只要加载的东西放到after-init-hook后就不会影响启动时间(实践中还是会有一点点耗时)。而init-file在after-init-hook前,如果init-file配置杂乱,没做好“按需加载”,很容易拖慢启动,所以我把init-file当作一个函数hook在after-init-hook后。init-file和after-init-hook后的其他东西一起加载,却又互补干扰。
2、虽然没有出错,但是对整个init-file进行add-hook,不知道有没有潜在的风险?如果没有,那每个包就无需再设置延迟加载。从启动速度这个角度来说,似乎with-eval-after-load :defer autoload等延迟技术就没多大意义了。
3、add-hook后可以接after-init-hook或者emacs-startup-hook,貌似前者要快一丢丢,而接window-setup-hook不能加载主题。
4、目前我的配置还很少,除了straight初始化和主题,其他的包还没配置上去,还需要继续验证其可行性和容错性。