vim処理速度調査(オートロード関数読み込み編)
以下の内容が書かれたファイルをautoload/speed1.vimとして置く。
function! speed1#nop() endfunction
同様に、autoload/speed1.vim、autoload/speed2.vim、...としてautoload/speed10.vimまで同様に置く。
そして、以下のスクリプトを:sourceする。
速度計測にはLeafCage/laptime.vimを使用する。
let lt = laptime#new() call speed1#nop() call lt.lap() call speed2#nop() call lt.lap() call speed3#nop() call lt.lap() call speed4#nop() call lt.lap() call speed5#nop() call lt.lap() call speed6#nop() call lt.lap() call speed7#nop() call lt.lap() call speed8#nop() call lt.lap() call speed9#nop() call lt.lap() call speed10#nop() call lt.end()
結果は以下のとおり
TOTAL LAP 1: 0.003770 0.003770 2: 0.007049 0.003279 3: 0.010308 0.003259 4: 0.013501 0.003194 5: 0.017289 0.003788 6: 0.021382 0.004093 7: 0.024573 0.003191 8: 0.027727 0.003153 9: 0.030940 0.003213 10: 0.034118 0.003179
内容の(ほとんどない)ない10のファイルを読み込むだけで計約0.034秒かかっている。
いったい何が原因なのか?
なぜ(ほとんど)空っぽのファイルをsourceするのにここまで時間がかかっているのか?
Vimはautoload関数が呼ばれるとruntimepathから該当ファイルを探してsourceするが、もしやここで時間がかかっているのかもしれない。
私はneobundle.vimでプラグインを管理しているが、その代償としてruntimepathに複数のパスが設定されている。
私のVim起動直後のruntimepathは以下のとおりであった。
runtimepath=~/vimfiles,~/box/vimfiles/neobundle/vim-fugitive,~/box/vimfiles/neobundle/vimproc,~/box/vimfiles/neobundle/tlib_vim,~/box/vim files/neobundle/vital.vim,~/box/vimfiles/neobundle/vim-openbuf,~/box/vimfiles/neobundle/curses-vim,~/box/vimfiles/neobundle/vim-submode,~/b ox/vimfiles/neobundle/vim-altr,~/box/vimfiles/neobundle/mdv,~/box/vimfiles/neobundle/vimhelpgenerator,~/box/vimfiles/neobundle/laptime.vim, ~/box/vimfiles/neobundle/neocomplcache,~/box/vimfiles/neobundle/neosnippet,~/box/vimfiles/neobundle/vim-operator-user,~/box/vimfiles/neobun dle/vim-textobj-user,~/box/vimfiles/neobundle/textobj-wiw,~/box/vimfiles/neobundle/vim-textobj-indent,~/box/vimfiles/neobundle/vim-textobj- plugins,~/box/vimfiles/neobundle/vim-textobj-xbrackets,~/box/vimfiles/neobundle/vim-textobj-parameter,~/box/vimfiles/neobundle/nerdcommente r,~/box/vimfiles/neobundle/ToggleCase-vim,~/box/vimfiles/neobundle/jasegment.vim,~/box/vimfiles/neobundle/clever-f.vim,~/box/vimfiles/neobu ndle/vim-ambicmd,~/box/vimfiles/neobundle/vim-altercmd,~/box/vim
そこで今度は:set rtp=~/vimfiles
として、runtimepathのパスを一つだけにしてから同じことをやってみた。
TOTAL LAP 1: 0.001546 0.001546 2: 0.002974 0.001428 3: 0.004392 0.001418 4: 0.005837 0.001445 5: 0.007338 0.001501 6: 0.008639 0.001301 7: 0.009950 0.001311 8: 0.011222 0.001271 9: 0.012507 0.001286 10: 0.014164 0.001656
処理時間が目に見えて短くなった(半分以下に)。すなわち時間がかかっている原因は、一つは探索場所が広大だったせいである。
だが、ちょっと待ってほしい。
確かに0.0015秒と短くなったとはいえ、これでもVimの処理の中では時間がかかってるほうである。拙作のプラグインにlaptime.vimというのがあるが、その関数の一つ、s:lt.end()のリストの要素が10個のときと同じくらいの時間がかかっている(これの実行時間は約0.0016秒)。
これはそれなりにリスト処理や文字列処理を含んでいる。つまりruntimepathを1つにして、探索場所を減らした状態でも、それなりの処理を含む1つの関数くらいの時間はかかっているわけである。
ちなみに、call speed1#nop()などの関数はほとんど何の仕事もしていないのであるが、これ自体の処理時間はおよそ0.0001秒である。二度目の関数呼び出しからはsourceの時間がなくなるので、この関数の時間だけしかかからず処理が高速になる。
参考
let s:test = range(101) call filter(s:test, 'v:val != "0"')
↑の処理時間は約0.0019秒前後
let s:test = range(101) call map(s:test, 'v:val. "yen"') call match(s:test, '25yen')
約0.002秒
let s:test = range(101) call map(s:test, 'v:val. "yen"') call filter(s:test, 'v:val != "0yen"')
約0.0039秒前後