読者です 読者をやめる 読者になる 読者になる

vimrc のどこが重いのかを調べるもう1つの方法

何やら mattn さんがプラグインを書いたみたい。

Big Sky :: vimrcのどこが重いのかを調べられるプラグイン書いた。

どうやらvimrcの各行にreltimeで時間差を取るコードを埋め込んで実行することで計測している模様。
ところでVimには+profileって機能がある。これを使うとVim scriptの各行が何回実行されてどれくらい時間がかかったのか調べられる。+profileはHuge版Vimでのみ使える。

早速やってみる

vimrc を計測したいのならコマンドラインから以下のようにする。

$ vim --cmd "profile start profile.txt" --cmd "profile file $HOME/.vimrc" +q && vim profile.txt

profile.txt に結果を吐き出すように設定してプロファイリングを開始し、.vimrc を計測対象に指定して、Vimが起動したら即座に終了している。そしてついでに結果をVimで開いている。プロファイル結果は Vim の終了時に書き出されるので、一旦終了する必要がある。:profile は ~/.vimrc みたいな表記は展開してくれないので注意。実際にはパターンが指定できるので、単に "profile file vimrc" でも動くと思う。Windows の人でも似たような感じでできるよ。
で、これの結果は以下のような感じ。

                            " Change statusline.
    1              0.000005 nnoremap <Space>s <Nop>
    1              0.000010 for [s:key, s:var] in [['n', 'bufnr'], ['c', 'char'],
    4              0.000010 \                      ['s', 'filesize'], ['h', 'highlight']]
   16              0.000050   for [s:prefix, s:scope] in [['', 'g'], ['b', 'b'], ['w', 'w']]
    1              0.000025   execute printf('nnoremap <silent> <Space>s%s%s '
                              \            . ':<C-u>call <SID>toggle_flag("%s:statusline_%s")<CR>',
   11              0.000221   \              s:prefix, s:key, s:scope, s:var)
   12              0.000012   endfor
    4              0.000003 endfor
    1              0.000004 unlet! s:key s:var s:prefix s:scope

ループを回しているところ。一番左が実行回数、右が合計時間。

    1   0.000030   0.000010 let s:movetab = ':<C-u>call ' . s:SIDP() . 'movetab(%d)<CR>'
    1   0.001337   0.000013 call submode#enter_with('movetab', 'n', '', '<Space>gt', printf(s:movetab, 1))
    1   0.000902   0.000015 call submode#enter_with('movetab', 'n', '', '<Space>gT', printf(s:movetab, -1))
    1   0.000425   0.000012 call submode#map('movetab', 'n', '', 't', printf(s:movetab, 1))
    1   0.000428   0.000012 call submode#map('movetab', 'n', '', 'T', printf(s:movetab, -1))
    1              0.000003 unlet s:movetab

関数を呼び出している場合は、左が合計時間、右が関数呼び出しを除いた時間。
こんな風になっているので、:%sort すればだいたい下の方に時間がかかった行が来る。

    1              0.000908 filetype off  " To reapply 'ftdetect/*.vim'.
    1              0.000913 filetype plugin indent on
    1              0.001128 set background=dark
      : (中略)
    1   0.001327   0.000010 call submode#enter_with('winsize', 'n', '', '<C-w>>', '<C-w>>')
    1   0.001328   0.000010 call submode#enter_with('diff', 'n', '', '<Space><Space>diff')
    1   0.001330   0.000010 call submode#enter_with('changetab', 'n', '', 'gt', 'gt')
    1   0.001335   0.000011 call submode#enter_with('change-list', 'n', '', 'g;', 'g;')
    1   0.001337   0.000013 call submode#enter_with('movetab', 'n', '', '<Space>gt', printf(s:movetab, 1))
    1   0.001338   0.000010 call submode#enter_with('textmanip', 'v', 'r', 'mv')
    1   0.002060   0.000015 call unite#set_substitute_pattern('file', '^;r', rtputil#split())
    4              0.000003 endfor
      : (中略)
   73              0.000250   let g:vimfiler_execute_file_list[s:i] = 'vim'

submode.vim が以外に塵積もだなー。ってことがわかった。使ってない設定はいっそ消してしまおうかな…。
みたいな感じでプラグインがなくてもお手軽に計測できるよ。
ちなみに "profile! file vimrc" のように ! を付けると、vimrc内で定義した関数の中身についてもプロファイリングしてくれる。sortで結果を見るのがやりづらくなるけど。
お試しあれ。