起動時に必ず読み込む必要ない関数ならautoloadを使う

設定を見直し中 - すぎゃーんメモ シリーズ。

例えばjs2-modeを設定する場合、起動時に読み込むelispファイルに

(autoload 'js2-mode "js2-mode" nil t)
(add-to-list 'auto-mode-alist '("\\.js$" . js2-mode))

のように書く、と説明が書いてある。このautoloadって何だろう、と思ってググってみたところ、

The autoload facility allows you to make a function or macro known in Lisp, but put off loading the file that defines it. The first call to the function automatically reads the proper file to install the real definition and other associated code, then runs the real definition as if it had been loaded all along.

http://www.gnu.org/savannah-checkouts/gnu/emacs/manual/html_node/elisp/Autoload.html

ようやくすると、関数やマクロを読み込んだことにして使えるように定義して、最初に呼び出されたときに初めて実際に定義を読み込んで実行する、ということのようで 起動速度を早めることができそう。 下記記事でも紹介されています。
ひとつの .emacs で設定を、、その2。 - 日々、とんは語る。
ただautoload-if-foundというのは自分の環境では使えなかった。消えちゃったのかな?


つまり、起動時に読み込むファイルで

(require 'js2-mode)
(add-to-list 'auto-mode-alist '("\\.js$" . js2-mode))

と書かれていると 起動時にjs2-mode.elが読み込まれて定義されるが、

(autoload 'js2-mode "js2-mode" nil t)
(add-to-list 'auto-mode-alist '("\\.js$" . js2-mode))

と書かれている場合は、起動時ではなく「初めて.jsファイルが開かれたとき」にjs2-mode.elが読み込まれて定義される、ということになる。という理解。なのでこうしておくと起動時の設定読み込みの速度が上がり、初めて.jsファイルを開いたときだけ少し遅くなる、という動作になる。

計ってみた

実際にrequireを使った場合とautoloadを使った場合でどれくらいロードにかかる時間がかわるのか。3回ずつくらい起動し直してinit-loader-show-logから調べてみた。

;; requireしている場合
loaded /Users/sugyan/.emacs.d/inits/22-js.el. 0.487208
loaded /Users/sugyan/.emacs.d/inits/22-js.el. 0.48945099999999997
loaded /Users/sugyan/.emacs.d/inits/22-js.el. 0.488544
;; autoloadを使った場合
loaded /Users/sugyan/.emacs.d/inits/22-js.el. 0.023364
loaded /Users/sugyan/.emacs.d/inits/22-js.el. 0.016505
loaded /Users/sugyan/.emacs.d/inits/22-js.el. 0.028277

だいぶ歴然。
# js2-modeをバイコンパイルしてないからかな、と思ったけどバイコンパイルしたら余計に遅くなった。。

結論

言語毎の設定など、「起動時に必ず読み込む必要があるわけではない」ものは、autoloadを使っておくと、初回起動の時間が短縮出来る。
とは言えコレが使えるのは"関数(もしくはmacro, keymap)"のみ、なのでrequireをそのまま置き換えられるわけではないので注意。