Jedi.vim と Vim の起動速度

あるいは、いかにして Vim の起動速度を取り戻したか。


いつのころか Vim の起動速度が遅くなった。
正確に言うと、Python のファイルを起動する際に遅い。


とりあえず起動時に何が遅いかプロファイルを取ってみた。

954.157  614.589  614.589: sourcing /Users/me/.vim/ftbundle/python/jedi-vim/./autoload/jedi.vim
954.426  617.175  002.586: sourcing /Users/me/.vim/ftbundle/python/jedi-vim/./ftplugin/python/jedi.vim
2947.941  1926.078  1926.078: sourcing /Users/me/.vim/ftbundle/python/jedi-vim/./autoload/jedi.vim
2948.210  1946.837  020.759: sourcing /Users/me/.vim/ftbundle/python/jedi-vim/./ftplugin/python/jedi.vim
757.152  499.467  499.467: sourcing /Users/me/.vim/ftbundle/python/jedi-vim/./autoload/jedi.vim
757.358  500.011  000.544: sourcing /Users/me/.vim/ftbundle/python/jedi-vim/./ftplugin/python/jedi.vim

速度が安定しないけど、酷い時で約 1.95sec 速い時で 500msec かかってる。
一度 Vim を起動して、すぐに再起動すると、もっと速い。
# OS のキャッシュにのせないため、マシンを再起動しながらやったから時間かかった…


いつからこんな遅くなったのかというのを調べてみた。

jedi-vim 0.7 jedi 0.7

108.692  000.672  000.672: sourcing /Users/me/.vim/ftbundle/python/jedi-vim/./ftplugin/python/jedi.vim
172.864  000.078  000.078: sourcing /Users/s_ohyanagi/.vim/ftbundle/python/jedi-vim/./after/./ftplugin/python/jedi.vim

速い。ただし補完の候補が出てくるのが遅い(最新は0.7 に比べると速い)。

jedi-vim 0.8 jedi 0.8

1255.951  984.472  984.472: sourcing /Users/me/.vim/ftbundle/python/jedi-vim/./autoload/jedi.vim
1256.185  1009.923  026.451: sourcing /Users/me/.vim/ftbundle/python/jedi-vim/./ftplugin/python/jedi.vim

どうやら 0.8 から遅くなった。


ソースコードを見ていると、0.7 に比べて jedi 自体がファイル数が増えている。
最新の jedi 0.9 になるともっと増えている。
プロファイル取るために全てのコードにデバッグコードを仕込んだわけではないが、おそらく Python のファイルの import に時間が掛かっている模様。


インポートが遅いのは Python 自体を速くする、マシンの性能を速くする、ファイル数を減らすなどをしないと無理なので、ちょっと簡単に手を出せない。


次に試したのが、Vim-Plug による lazy load。
Vim-Plug とかそこら辺のプラグインマネージャ系は lazy load があるそうなので試してみた。
結果は対して変らない。
Lazy load ってのが filetype が python の時に読み込むというのが lazy load やら on demand load という事ならそらそうだ。
もともと unbundle.vim を使って filetype ごとのロードしかしていない。
# 余談だけど、vimrc とかに読み込むプラグイン候補をいちいち書くの、めんどくさかった


どうしたもんかと思っていたら、Vim 自体のパッケージ機能は使えないかと思ったら、タイムリーに
vim pluginのbackground loading - daisuzu's notes を読んだ。


MacVim Kaoriya(7.4 1-1537) にはまだタイマー機能は入っていなかったが、 Vimのパッケージ機能を試してみました - Blank File にある遅延読み込みをすれば出来るんじゃないかと思い、試してみた。

" ~/.vim/config/plugins.vim に定義
function! LazyLoadPython() abort
  packadd jedi-vim
  packadd pyflakes-vim
  packadd vim-autopep8
  packadd vim-virtualenv
  set filetype=python
  autocmd! lazy_load_python
endfunction

" .vimrc に定義
autocmd VimEnter * source ~/.vim/config/plugins.vim
augroup lazy_load_python
  autocmd! InsertEnter *.py :call LazyLoadPython()
  autocmd Filetype python    setlocal omnifunc=jedi#completions
augroup END

タイマー機能でバックグラウンドで読み込みたいが、まだできないので、とりあえず初回のインサートモードに入った際に実行するようにした。

これで Vim の起動速度が以下の感じになった。

jedi-vim 0.7 191.565
jedi-vim 0.8 482.318
jedi-vim 0.9 1015.580
pack 178.358

ただこれでもインサートモードの最初は遅いので、早くタイマー機能使ってバックグラウンドで読み込みさせたい。

Pack について

Pack については、Vimのパッケージ機能を試してみました - Blank File にあるとおり、ハマりどころがある。
完全に stable になっているわけではないし、変更が色々入る可能性が高い。
ただ packadd したらプラグインが有効になるという設計は素晴らしいと思った。
タイマー機能が安定して使えるようになれば、完全にバックグラウンドで遅延読み込みができる。


vimrc などに読み込むパッケージを定義しなくて良いのも素晴らしい。
自分は気になるプラグインを git clone して Vim を起動するだけにしたいので、自分の使い方にもあっている。