idle-require.elでEmacsの起動を高速にする


Emacsは、標準の状態では正直使い勝手の良い代物ではありません。いろいろと手を加えることで至高の環境になると思うのですが、そこで新たに問題となってくるのが起動時間。便利なelispを導入するほど起動に時間がかかるようになってきます。特にこれがないとやってられないってくらい重要なelispに限って重量級なことが多く、例えば当方のPCだとyasnippet.elでは1.3秒、anything.elに至っては2秒弱ほど読みこむのに時間がかかっています。
ええ、知ってますとも。Emacsは一度起動したら終了せずに使うものだということを。そして、emacsclientという便利なものもあることを。
ただ、シャバはそんなに甘くありませんです。Emacsだって不意に落ちることはあります。非力なPCで使っていれば、メモリを開放するためやむなくEmacsを終了することだってあります。emacsclientはすごく便利なので、すぐに使えるようにPCを起動した際に自動的にemacs –daemonを起動するように設定しているのですが、Emacs自体の起動時間がかかるようになると、そもそもPC自体の起動が遅くなるという便利なのか不便なのかよくわからない状況になっていました。
これではいけません。

requireをautoloadに置き換え

起動時間に関する問題は今に始まったことではないので、Emacs自体にも高速化のための機能が備わっています。その一つがautoloadです。これは、autoloadに引数として渡される関数が呼ばれた時にファイルをロードするというものです。特にメジャーモード、マイナーモードをロードする時には、積極的にrequireをautoloadに置きかえるようにしてます。autoloadについては以下のサイトで詳しく説明されています。

GNU Emacs Lispリファレンスマニュアル: Autoload
ひとつの .emacs で設定を、、その2。 – 日々、とんは語る。
autoload-if-found に関数リストを渡したい – jimo/memo
Meadow/Emacs memo: Meadow 関連の少し高度な知識

idle-require.elでさらに高速化

autoloadはメジャーモードなどロードする関数が集約的な時にはその威力を発揮しますが、ユーティリティ関数などが複数含まれたものだと関数全てに対して書く必要があるのでかなり面倒です。
そういった関数にはマジックコメントを用いたautoloadの方法も提供されているのですが、ソースコードに直書きしないといけないのでお行儀も良くありませんし、開発者による今後のアップデートのことも考えればあまり良い方法ではなさそうです。
ここで、idle-require.elの出番です。
idle-require
idle-require.elは、provideされているelispをEmacsが起動した後に遅延ロードするのを補助するものです。使いかたもいたって簡単。まず.emacsとかの先頭の方に(require ‘idle-require) (idle-require-mode 1)と書いて読みこみます。後は遅延ロードしたいelispでrequireされてるものをidle-requireで読みこみます。例えば、これまで(require ‘hogehoge)等として読みこんでいたのを(idle-require ‘hogehoge)と書きかえれば良いだけです。とても簡単です。
ただ、公開されているものだとロードの順番が逆になってしまうのが嫌だったので少し修正してみました。修正したものはgistに置いてます。

ひたすら高速化

後は、autoloadなりidle-require.elを使って起動時間を縮めていきます。起動時間の計測にはこちらの方法を使わせてもらいました。その結果、僕の環境では、1秒を切るくらいの速度で起動できるようになりました。特にidle-require.elについてはemacsclientとの相性がすこぶる良いと思いました。emacsclientはPCを起動してすぐ使うという代物でもないので、とりあえず後でチマチマ読みこむようにしておいて、起動時間だけを短縮しておけば、気兼ねなくPCの起動に合わせてemacs –daemonを起動できます。
ただ、何でもかんでも遅延させれば良いってものでもなく、あくまで使い勝手とのトレードオフです。
てことで、ご利用は計画的に。。。