はじめに Emacsの起動高速化については、とても定評がある記事がある。
Emacsの起動時間を""詰める"" Emacsを世界最速級で起動する方法 これを参考にすれば誰でも起動速度を"詰める"ことはできるはずで、あまり俺ごときが追加で書くような 話はないのだが、自分なりのメモを残しておこうと思う。
leaf.elとpackage.elでの起動高速化を目指す 本件はleafでパッケージ設定を書き、パッケージ管理をpackage.elにまかせつつ高速化する話で、 実のところ最速を狙う手法ではない。まあ最速じゃなくてきっと意味はあるよね……ということで。
遅延初期化 通常Emacsでの遅延初期化は、他の.elを読んだら評価する(with-eval-after-load)や、 書かれた関数・変数が使われたら呼ぶ(autoload)に頼ることになるのだが、 package.elを使いつつemacs-init-timeを100ms未満にしようとするなら、もう一歩踏み込む必要がある。
遅延実行 まず、Emacsを起動した後、あまり使わないパッケージの初期化が全部終わってなくてもエディットは 始めていいはずだ。よって、よくある例と同様にEmacs起動後に遅延評価させるようにする。
;; after-init-hookで順次登録された関数を実行する (defvar my/delayed-configs nil) (defvar my/delayed-config-timer nil) (defvar my/delayed-config-done nil) (eval-and-compile (defconst my/prio-low 1) (defconst my/prio-normal 10) (defconst my/prio-urgent 100)) (defun my/add-to-delayed-configs (priority config) "Add CONFIG with PRIORITY to delayed configs." (if my/delayed-config-done (condition-case err (eval config) (error (message "my/delayed-config exection error: %s" err))) (push (cons priority config) my/delayed-configs) ;; sort the configs by priority (setq my/delayed-configs (sort my/delayed-configs (lambda (a b) (> (car a) (car b))))))) (defun my/execute-config (config) "Execute a single delayed CONFIG safely." (let ((inhibit-message t)) (condition-case err (eval config) (error (message "my/delayed-config execution error: %s" err))))) (defun my/execute-delayed-configs () "Execute delayed configs using timer for urgent priority and idle timer for others." (if my/delayed-configs (let* ((config-pair (pop my/delayed-configs)) (priority (car config-pair)) (config (cdr config-pair))) (if (>= priority my/prio-urgent) ;; For urgent priority, use run-with-timer (run-with-timer 0.1 nil (lambda () (my/execute-config config) (my/execute-delayed-configs))) ;; For normal and low priority, use run-with-idle-timer (run-with-idle-timer (if (>= priority my/prio-normal) 0.5 1.0) nil (lambda () (my/execute-config config) (my/execute-delayed-configs))))) (setq my/delayed-config-done t))) (add-hook 'after-init-hook 'my/execute-delayed-configs) (defmacro with-delayed-startup-exec (priority &rest body) "Execute BODY after init with delay, according to PRIORITY." (declare (indent 1)) `(my/add-to-delayed-configs ,priority ',(cons 'progn body))) priorityをつけたので先例より実装がちょっとだけ大きくなったが、見ての通り大した事はしてない。
...