最近のMeCabの使い方
MeCabはC/C++で書かれた形態素解析を行うライブラリなのですが、ちょっと疑問に思うところがあって、以下のようなコードを書きました。
require 'MeCab' mecab_options = '-Owakati' 1000.times do |n| begin tagger = MeCab::Tagger.new(mecab_options) # do something with tagger rescue => e raise "failed at #{n + 1} times, [#{e.class}] #{e.message}" end end
マシンスペックに依りますが、大体例外が発生します。MeCab::Taggerのインスタンスが破棄されているにも関わらず! 僕のMacBook Air(メモリ2GB)で試したところ、"failed at 70 times, [RuntimeError] "と、大体70回MeCab::Tagger.newを呼んだところで落ちます。例外の内容は不明。
プロセスどうなってんのと見てみると、メモリを13GBほど消費してました。ひどい。多分mallocに失敗とかそんなところでしょうか?
どうやらMeCab 0.99からマルチスレッドに対応したようで、本家のドキュメントのコード例も変わってました。要はマルチスレッドでMeCab::Taggerのインスタンスをもりもり作る場合はMeCab::Modelのインスタンスを作り、そこからMeCab::Taggerのインスタンスを生成しろよ、ってことみたいです。もしMeCab::Taggerのインスタンスを直接生成すると、そのたびにMeCab::Modelのインスタンスが生成されるので、メモリを圧迫し、死亡、という流れのようですね。
ということでMeCab 0.99をインストールしている環境では以下のように書けば大丈夫みたいです。
require 'MeCab' mecab_options = '-Owakati' mecab_model = MeCab::Model.create(mecab_options) 1000.times do tagger = mecab_model.createTagger # do something with tagger end
ちなみにMeCab::Taggerをひとつしか生成しないような環境であれば、MeCab::Taggerから直接インスタンスを生成しても構いません(コード例でもそう書いてある)。