このGWは、自分のEmacsを磨くことに費やしておりました。
Emacsは、御存知のとおり非常にカスタマイズ性の高いエディタです。
しかし、「ぼくのさいきょうのえでぃた」を作ろうとして無闇矢鱈にカスタマイズしたり、パッケージを追加したりして、Emacsを膨らませすぎると起動時間が非常に遅くなります。
私のEmacsも非常に起動時間が遅くなっておりました。
けれども「Emacsは一度起動したら起動しっぱなしにしておくもの」であるため、あまり気になるものではありませんでした。
しかし、最近になってパソコンを付けっぱなしにしておく癖は如何なものかと考えるようになり、頻繁に再起動するようになりました。
そうなると、Emacsの起動時間が気になるようになります。
そこで、このGWを機にEmacsの起動時間を改善しようとしました。
はじめに
自分のEmacsにおける問題
- バイトコンパイルとしているものとしていないものがある。
- 起動時に全てのパッケージを読み込んでいた。
- 使わないパッケージすら読み込んでいる。
これらが最初に上げられました。
全てのelファイルをバイトコンパイルしていない問題
これはいちいち、変更を加える度にバイトコンパイルをするのが面倒だったことが理由です。
しかし、バイトコンパイルをしなければ、読み込み時間は遅くなります。
そこで、自動コンパイルすることを考えたのですが、既にパッケージになっていました。
それは、るびきちさんが作ったパッケージ「auto-async-byte-compile」です。
これは、自動的に非同期的に編集したelをバイトコンパイルしてくれるというスグレモノだそうです。
これを導入することで、ひとまずはこの問題は解決できました。
起動時に全てのパッケージを読み込んでいた。
これは私の知識不足が原因でした。
これまで、EmacsLispのパッケージを読み込むときは以下のようにしていました。
(require 'package-name)
(パッケージの利用)
全てのパッケージをこのように書いていたのです。
これによって、起動の時点で全てのパッケージがロードされてしまったのです。
つまり、これが起動が遅くなる原因の一つになったといえます。
そこで、一度にパッケージを読み込まない方法を調べました。
するとautoloadという関数とeval-after-loadという関数を知りました。
この項でしゃ、autoloadに関する説明を行います。
autoloadとは以下のように使います。
(autoload 'packge-function "package-name" nil t)
先ほどの require は、ただそのファイルをロードする関数です。
しかし、 autoload は最初の引数に関数名のシンボルを置き、次の引数に読み込みたいファイル名を入れます。それ以降の引数については、ここを読んでください。
これはシンボルにした関数やマクロ 'package-function を最初に定義されたことにしておき、その関数の実行時にそのパッケージ "package-name" をロードするというものです。
※注意点は、パッケージ名 "package-name" は文字列でないと型が違うと怒られます。
これによって、起動時の時点でいらないパッケージを読み込まずに済みます。
この関数は、あるパッケージを使う際にそのパッケージで最初に使う関数が実行されるまで読み込まないようにするために使えます。
以下はその例です。
(autoload 'enh-ruby-mode "enh-ruby-mode"
"Major mode for ruby files" t)
これは、 enh-ruby-mode が実際に呼び出されるまでこのパッケージがロードされないことを意味します。
つまり、Rubyのファイルを開くまでパッケージがロードされません。
使わないパッケージすら読み込んでいた。
先ほど紹介した eval-after-load というものの説明です。
この関数は以下のように使います。
(eval-after-load 'filename '(様々な処理))
これは最初の引数 'filename の名前のファイルが読み込まれた後に、その次の引数 '(様々な処理) の処理がロードされるという関数です。
この関数は、あるファイルが読みまれるまで読み込む必要のないパッケージロードしないようにしたり、関数を実行しないようにしたりするために使えます。
以下はその例です。
(eval-after-load 'enh-ruby-mode '(require 'rubocop))
これは、 enh-ruby-mode が実行されるまで rubocopパッケージをロードしないことを意味しています。
つまり、rubyファイルを開いて初めてrubocopパッケージが読み込まれます。
二つ目の引数である”後に実行したい処理”を複数行書く場合は、 progn に包んで書いていたようです。
しかし、今は以下の様な書き方があり、簡単に複数行に渡る処理が書けます。
(with-eval-after-load 'filename
(様々な処理1)
(様々な処理2)
...
(様々な処理n))
ということだそうです。
最後に
間違ってる所があったら指摘お願いします……。