Emacs启动时间分析
1 介绍
Emacs启动调优需要先分析时间分布。benchmark-init和esup是两个优秀的候选package。 benchmark-init有更好的分析粒度,修改配置文件时调用esup函数可即刻查看启动时间花费。
我的配置]]使用init.el进行最小基本配置,org文学编程维护绝大多数配置项。init.el仅进行proxy、package-archives、use-package配置,其他都位于config.org中,通过
org-babel-load-file
加载。我将benchmark-init和esup都在config.org起始处,忽略
init.el本身启动时间分析。
2 benchmark-init
benchmark-init是require和load函数的基准测试工具:
This is a simple benchmark of calls to Emacs require and load functions. It can be used to keep track of where time is being spent during Emacs startup in order to optimize startup times.
The code was originally based on init-benchmarking.el by Steve Purcell with many additional modifications having gone into it since.
benchmark-init配置如下:
#+BEGIN_SRC emacs-lisp
(use-package benchmark-init
:init
(benchmark-init/activate)
:hook
(after-init . benchmark-init/deactivate))
#+END_SRC
调用函数 benchmark-init/show-durations-tree
和
benchmark-init/show-durations-tabulated
以树或表格方式显示结果。
benchmark-init/show-durations
是 benchmark-init/show-durations-tabulated
别名。如下是一次启动部分内容截取:
Benchmark results ╼►[benchmark-init/root nil 619ms] ├─[company-dabbrev require 1ms] ├─[company-capf require 0ms] ├─[company-cmake require 0ms] ├─[company-clang require 1ms] ├─[company-eclim require 1ms] │ ╰─[company-template require 1ms] ├─[pcase require 2ms] ├─[default load 3ms] ├─[ivy-overlay require 2ms] ├─[ffap require 45ms] ├─[auto-complete-c-headers require 0ms] │ ╰─[cl require 2ms] ├─[ggtags require 4ms] │ ├─[etags require 3ms] │ │ ╰─[xref require 5ms] │ │ ╰─[project require 4ms] │ ╰─[ewoc require 3ms] ...
Module Type ms ^ total ms pdf-view require 78 126 ffap require 45 45 semantic/loaddefs load 41 41 semantic/find require 39 39 eieio-speedbar require 37 50 pdf-info require 36 38 cc-vars require 34 34 lisp-mnt require 32 32 cc-mode require 10 71 cus-edit require 8 8 ede/base require 7 10 cc-engine require 6 6 ...
3 esup
esup对emacs启动时间进行基准分析。esup-0.6版本在emacs-26.0.90版本下有 package format striing错误,参见issues 46描述,此问题已在腌a589005 提交中解决,但截至当前还无法在melpa下安装,git clone esup并替换elpa目录下的 esup-child.el并手动编译:
<cd your directory> git clone https://github.com/jschaf/esup.git cp esup/esup-child.el ~/.emacs.d/elpa/esup-0.6/ <start your emacs then call @byte-compile-file file ~/.emacs.d/elpa/esup-0.6/esup-child.el>
esup无法对org-babel加载文件的子条目进行析(即使设置分析深度变量
esup-child-profile-require-level
也是如此)。而我的配置绝大多数在
config.org中,因此写了一个wrapper函数协助:
#+BEGIN_SRC emacs-lisp
;; evaluate emacs starting time
(when (getenv "ESUP_PROFILER")
(progn
;; init.el does not evaluated when call y:esup
;; then load init.el diretly here
(message "Import init.el for ESUP_PROFILER.")
(load-file (expand-file-name "init.el" user-emacs-directory))))
(defun y:esup()
"Profiler Emacs Startup Time."
(interactive)
(when (fboundp 'esup)
(progn
;; First set env then load init.el to avoid recursive includes.
(setenv "ESUP_PROFILER" "t")
(esup (expand-file-name "config.el" user-emacs-directory)))))
(use-package esup
:init
(setq esup-child-profile-require-level 2))
#+END_SRC
调用函数 y:esup
查看结果:
config.el:624 0.176sec 8% (use-package yasnippet :diminish yas-minor-mode :init (yas-global-mode 1)) config.el:506 0.119sec 5% (use-package auto-complete-config :diminish auto-complete-mode :ensure auto-complete :init (ac-config-default)) config.el:103 0.104sec 5% (when (fboundp 'tool-bar-mode) (tool-bar-mode -1)) config.el:122 0.088sec 4% (use-package monokai-theme :init (load-theme 'monokai t)) ...
也可调用 esup
分析,但只能显示config.org总时间。如果配置全部在init.el文件中,调用esup也可达成分析目的:
init.el:142 1.427sec 73% (unless (getenv "ESUP_PROFILER") (org-babel-load-file (expand-file-name "config.org" user-emacs-directory)))
esup默认分析 user-init-file
文件,执行 C-u M-x esup
可指定其他文件名。