Vim scriptは実行されない行を解釈しているので遅いという件についてサンプルコードを書いてみた
元ネタ:map, fold, filter on Vim Script - Togetter
@manga_osyo vimスクリプトは、構文解析が expr1 から expr7 というカテゴライズされた文脈解析を「動的に」行っていて、遅くなる原因は、vim script とC言語を行き来する回数に比例しますね。なのでmapでも式が多いと遅いし、forが速いケースもある。
2012-11-15 09:54:19 via TwitVim to @manga_osyo
vim script が気持ち悪い理由の一つに式を動的に、行単位で解析しているので、if 0 の後 else を探す為に通らない部分のコードをガリガリ無効化しながらパースしている。これが遅い。
なので if else endif ではよく通る方を if true とした部分に書くと、幾分速くなる可能性がある。もちろん else がくるまでに return する。
そうなのかー。ということで簡単なサンプルを書いて確認してみた。
サンプルコード
実行結果を最後に載せます。先にサンプルコードから。
ケース1:trueもfalseも短い。基準に使う
function! s:base() if 0 let a = {'a':1} else let b = {'b':1} endif endfunction
ケース2:falseが上に来ていて、その中のコードが10000行ある
function! s:false_ga_ue_de_nagai() if 0 let a = {'a':1} " 以下同じコードが9999行続く else let b = {'b':1} endif endfunction
ケース3:ケース2と同じだけど、10000行の中身を別関数に切り出してある
function! s:false_ga_ue_de_nagai_kedo_func() if 0 call s:nagai_func() else let b = {'b':1} endif endfunction function! s:nagai_func() let a = {'a':1} " 以下同じコードが9999行続く endfunction
ケース4:trueが上に来ていて中身も短いんだけど、returnがない。そしてfalse部が10000行。
function! s:true_ga_ue_de_mijikai_kedo_return_nashi() if 1 let b = {'b':1} else let a = {'a':1} " 以下同じコードが9999行続く endfunction
ケース5:trueが上に来ていて中身も短くてreturnがある。そしてfalse部が10000行。
function! s:true_ga_ue_de_mijikai_kedo_return_ari() if 1 let b = {'b':1} return else let a = {'a':1} " 以下同じコードが9999行続く endfunction
これらに対して簡単に実行時間を計測しました。
計測には以下のプラグインを使っています。
Vim script のベンチマーク - Alone Like a Rhinoceros Horn
let s:bm = benchmark#new("sample") function! s:bm.base() call s:base() endfunction function! s:bm.false_ga_ue_de_nagai() call s:false_ga_ue_de_nagai() endfunction function! s:bm.false_ga_ue_de_nagai_kedo_func() call s:false_ga_ue_de_nagai_kedo_func() endfunction function! s:bm.true_ga_ue_de_mijikai_kedo_return_nashi() call s:true_ga_ue_de_mijikai_kedo_return_nashi() endfunction function! s:bm.true_ga_ue_de_mijikai_kedo_return_ari() call s:true_ga_ue_de_mijikai_kedo_return_ari() endfunction call s:bm.run(3)
実行結果
Benchmark: sample Trial #1 true_ga_ue_de_mijikai_kedo_return_ari : 0.000030 base : 0.000034 false_ga_ue_de_nagai_kedo_func : 0.000058 true_ga_ue_de_mijikai_kedo_return_nashi : 0.012003 false_ga_ue_de_nagai : 0.012866 Trial #2 false_ga_ue_de_nagai_kedo_func : 0.000030 true_ga_ue_de_mijikai_kedo_return_ari : 0.000031 base : 0.000035 false_ga_ue_de_nagai : 0.011730 true_ga_ue_de_mijikai_kedo_return_nashi : 0.012302 Trial #3 base : 0.000029 false_ga_ue_de_nagai_kedo_func : 0.000029 true_ga_ue_de_mijikai_kedo_return_ari : 0.000030 true_ga_ue_de_mijikai_kedo_return_nashi : 0.011757 false_ga_ue_de_nagai : 0.012152
「すぐにreturnした場合」と「関数に切り出した場合」は特に影響なさそうですが、
「returnがない場合」と「falseだけど長い」のは目に見えて遅くなっています。
多くの場合は気にするほどの速度差ではないのかもしれませんが、覚えておくといいことあるかも。