Text::MeCabの処理時間
Text::MeCabでのわかち書き処理が遅い件について、記録を取っていなかったので再度処理時間を計り直しました。
用意した文章は次のものをUTF-8に変換したものです。
MeCab
$ time mecab -Owakati < ~/spam-utf8.txt > /dev/null real 0m0.009s user 0m0.004s sys 0m0.004s $ time mecab -Owakati < ~/binzume_jigoku.txt > /dev/null real 0m0.045s user 0m0.032s sys 0m0.012s $ time mecab -Owakati < ~/kokushikan.txt > /dev/null real 0m1.357s user 0m1.336s sys 0m0.020s
mecab-perl
$ cat wakati-mecab.pl #!/usr/bin/perl -w use strict; use MeCab; $/ = undef; my $str = <STDIN>; my $mecab = MeCab::Tagger->new("-Owakati"); my $tokenized = $mecab->parse($str); print $tokenized; exit 0; $ time ./wakati-mecab.pl < spam-utf8.txt > /dev/null real 0m0.049s user 0m0.036s sys 0m0.016s $ time ./wakati-mecab.pl < binzume_jigoku.txt > /dev/null real 0m0.086s user 0m0.068s sys 0m0.016s $ time ./wakati-mecab.pl < kokushikan.txt > /dev/null real 0m1.535s user 0m1.308s sys 0m0.228s
Text::MeCab
$ cat wakati-text-mecab.pl #!/usr/bin/perl -w use strict; use Text::MeCab; $/ = undef; my $str = <STDIN>; my @buf; my $mecab = Text::MeCab->new({output_format_type => 'wakati'}); for (my $node = $mecab->parse($str); $node; $node = $node->next) { push(@buf, $node->surface); } my $tokenized = join(' ', @buf) . "\n"; print $tokenized; exit 0; $ time ./wakati-text-mecab.pl < spam-utf8.txt > /dev/null real 0m0.043s user 0m0.028s sys 0m0.016s $ time ./wakati-text-mecab.pl < binzume_jigoku.txt > /dev/null real 0m0.641s user 0m0.616s sys 0m0.024s $ time ./wakati-text-mecab.pl < kokushikan.txt > /dev/null 15分以上経っても終わらなかったので中断。
Text:Kakasi
$ cat wakati-kakasi.pl #!/usr/bin/perl -w use strict; use Encode; use Text::Kakasi; $/ =undef; my $text = <STDIN>; my $kakasi = Text::Kakasi->new(qw/-iutf8 -outf8 -w/); my $tokenized = Encode::encode_utf8($kakasi->get($text)); print $tokenized; exit 0; $ time ./wakati-kakasi.pl < spam-utf8.txt > /dev/null real 0m0.101s user 0m0.080s sys 0m0.016s $ time ./wakati-kakasi.pl < binzume_jigoku.txt > /dev/null real 0m0.180s user 0m0.144s sys 0m0.036s $ time ./wakati-kakasi.pl < kokushikan.txt > /dev/null real 0m1.658s user 0m1.576s sys 0m0.084s
結果
ファイルサイズ[バイト] | MeCab[秒] | mecab-perl[秒] | Text::MeCab[秒] | Text::Kakasi |
1767 | 0.009 | 0.049 | 0.043 | 0.101 |
25496 | 0.045 | 0.086 | 0.641 | 0.180 |
1039324 | 1.357 | 1.535 | - | 1.658 |
Text::MeCabの場合は文章サイズが大きくなると致命的に処理が遅くなるようです。
ちなみにText:MeCabによる『黒死館殺人事件』の処理を中断する前のtopコマンドの出力は次のようになります。
Tasks: 81 total, 2 running, 79 sleeping, 0 stopped, 0 zombie Cpu(s): 100.0% us, 0.0% sy, 0.0% ni, 0.0% id, 0.0% wa, 0.0% hi, 0.0% si, Mem: 2067640k total, 657180k used, 1410460k free, 98620k buffers Swap: 0k total, 0k used, 0k free, 243604k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 5965 taki 25 0 240m 218m 34m R 99.7 10.8 12:04.22 wakati-text-mec
たかだか1Mバイトのテキストファイルを処理しているだけなのに異様にメモリを消費しています。
forループ等のオーバーヘッドが原因ではないと思うので、念のため確認をしてみました。『瓶詰地獄』の処理を擬似的に模すために5バイトの文字を5637回(実際のループ回数)加えてみました。
$ cat wakati-text-mecab-dummy.pl #!/usr/bin/perl -w use strict; my @buf; my $text = "12345"; for (1..5637) { push(@buf, $text); } my $tokenized = join(' ', @buf) . "\n"; print $tokenized; exit 0; $ time ./wakati-text-mecab-dummy.pl > /dev/null real 0m0.018s user 0m0.012s sys 0m0.004s
比較すると次のようになり、forループ等の影響はそれほど大きくはないことがわかります。
MeCab[秒] | mecab-perl[秒] | Text::MeCab[秒] | ダミー[秒] |
0.045 | 0.086 | 0.641 | 0.018 |
こんなところですが、これで何かわかりますでしょうか?>dmakiさん