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

Gomoku: MeCabと形態素解析速度比較

Java speed

Igoの時と同じように、Gomoku(0.0.4)MeCab(0.98)形態素解析速度を比較してみた。

計時結果

テキストには青空文庫より取得の夏目漱石の『こころ』(x256. 136M. UTF-8)を、辞書にはMeCabのサイトより入手可能なmecab-ipadic-2.7.0-20070801*1を使用。

総処理時間(1)行読み込み時間(2)1 - 2
MeCab34.781s0.134s34.647s
Gomoku33.313s0.989s32.324s
例によって適当な比較なので何とも云えないけど、今回測った限りではMeCabよりも速くなっている*2 *3

計時用のプログラム

MeCabの計時に用いたプログラム:

/**
 * ファイル名: mec.cc
 * コンパイル: g++ -O3 -omec mec.cc `mecab-config --libs`
 * 計時方法: time mec <対象ファイル>
 *
 * gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5)
 */
#include <mecab.h>
#include "read_line.h"
#include <cstdio>

int main(int argc, char** argv) {
  mecab_t* m = mecab_new2("-Owakati");
  ReadLine rl(argv[1]);
  const char* line;

  // 以下、Igoの時はmecab_sparse_tostr関数を使っていたがtonode関数の方が若干高速なので、こちらを使用
  while(line=rl.read()) {
    // 行読み込み自体の処理時間を計る時は、以下の一行をコメントアウトする
    mecab_sparse_tonode(m,line);  
  }

  mecab_destroy(m);
  return 10;
}
// read_line.h
#ifndef READ_LINE_H
#define READ_LINE_H

#include <cstring>
#include <vector>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

class ReadLine {
public:
  ReadLine(const char* filepath) : buf(NULL),index(0) {
    int f = open(filepath, O_RDONLY);
    if(f==-1)
      return;
    
    struct stat statbuf;
    fstat(f, &statbuf);

    buf = new char[statbuf.st_size+1];
    ::read(f, buf, statbuf.st_size);
    close(f);

    buf[statbuf.st_size]='\0';

    init(buf,buf+statbuf.st_size-1);
  }
  ~ReadLine() {
    delete [] buf;
  }

  operator bool() const { 
    return buf!=NULL;
  }

  void reset() {
    index = 0;
  }

  const char* read() {
    if(index == lines.size())
      return NULL;

    return lines[index++];
  }

private:
  void init(char* cur,const char* end) {
    lines.push_back(cur);
    for(cur=strchr(cur,'\n'); cur; cur=strchr(cur,'\n')) {
      *cur = '\0';
      cur++;
      if(cur < end)
        lines.push_back(cur);
    }
  }

private:
  char* buf;
  std::size_t index;
  std::vector<const char*> lines;
};

#endif

Gomokuの計時に用いたプログラム:

/**
 * ファイル名: GomokuBench.java
 * コンパイル: javac -cp gomoku-0.0.4.jar GomokuBench.java
 * 実行 方法: java -cp .:gomoku-0.0.4.jar GomokuBench  <  入力ファイル
 */
import java.io.IOException;
import net.reduls.gomoku.Tagger;
import net.reduls.gomoku.Morpheme;
import net.reduls.gomoku.util.ReadLine;

public final class GomokuBench {
    public static void main(String[] args) throws IOException {
	final ReadLine rl = new ReadLine(System.in);
        for(String s=rl.read(); s != null; s=rl.read()) {
            // 行読み込み自体の処理時間を計る時は、以下の一行をコメントアウトする
            Tagger.wakati(s);
        }
    }   
}

*1:gomoku-0.0.4.jarに組み込まれているのもこの辞書

*2:今回のGomokuの開発で得た知見をIgoにもフィードバックすれば、もしかしたらIgoの方も速くなるのかな?

*3:2011/01/27追記: 別の環境、別のデータで試したら、Gomokuが11.440秒、MeCabが10.228秒、とMeCabの方が速かった。