MeCab の Ruby 各種ライブラリをベンチ取ってみた
前書き
たっくん(@takkkun)との会話
「MeCab の Ruby Binding、SWIG 使ってるから MeCab と密結合してて、手元とサーバで MeCab のバージョンが違う時にインストールするの面倒臭いんだよね」
「Natto gem 使えば良いじゃん」
「Natto gem 遅いんだよ」
前提条件
MeCab のバージョンは 0.996 を使用
ベンチマークは parse メソッド(mecab_parse_tostr 関数)のみを対象とする
何故 Natto gem が遅いのか調べた
Natto::MeCab#parse メソッド内で、初期化時に作成された無名関数を呼んでること、ブロックがあった場合の処理の切り分けをしてること、ヘルパー経由でエンコーディングしてることがボトルネックになっていることが分かった
ここの条件分岐やヘルパーメソッドの呼び出しをなくしハードコードしてみると MeCab 公式の Ruby Binding と速度があまり変わらないことが分かった
ベンチマーク結果
以下はベンチマークに使ったコード
ffi を使って簡易的に作ったバージョンも載せてる
ベンチマーク結果
Rehearsal ---------------------------------------------- 和布蕪 0.090000 0.000000 0.090000 ( 0.100041) 納豆 0.130000 0.000000 0.130000 ( 0.127894) 大豆納豆 0.090000 0.000000 0.090000 ( 0.093463) ネギトロ 0.100000 0.010000 0.110000 ( 0.101709) ------------------------------------- total: 0.420000sec user system total real 和布蕪 0.090000 0.000000 0.090000 ( 0.090971) 納豆 0.120000 0.000000 0.120000 ( 0.124085) 大豆納豆 0.090000 0.000000 0.090000 ( 0.090563) ネギトロ 0.100000 0.000000 0.100000 ( 0.094437)
元の Natto gem 以外はほとんど速度が変わらないことが分かった
追記
Twitter で指摘頂きました
これは良いベンチ。ちなみに僕も手元でベンチ取ったけど、解析する文字列の長さでも速度に差が出てた / MeCab の Ruby 各種ライブラリをベンチ取ってみた - life.stub(:happy?).and_return(true) http://t.co/Ljgjrhj3I4
— たっくん (@takkkun) April 21, 2013
具体的には解析する文字列が短いほどmecab-rubyが、長いほどffiが速いって結果だった。結局、短いと、処理時間よりもオーバヘッドの比率が大きくなり、オーバヘッド的に優位なC拡張の方が速いってのは分かるけど、長いとffiの方が速いってのは理由が分からんかった
— たっくん (@takkkun) April 21, 2013
関連リンク
MeCab: Yet Another Part-of-Speech and Morphological Analyzer