最速KVS研究会:Google Level DB対Kyoto Cabinet

Google LeveDBは,前回までにインストールしてあったリビジョン36を使うことにします.
svn updateするとなぜかエラーになった)

> wget http://fallabs.com/kyotocabinet/pkg/kyotocabinet-1.2.65.tar.gz
> tar xvf kyotocabinet-1.2.65.tar.gz
> cd kyotocabinet-1.2.65
> ./configure --enable-lzo
> make
(中略)
g++ -march=native -g -O2 -Wall -fPIC -fsigned-char -g0 -O2 -o kcutiltest  -L. -L/usr/local/lib -L/usr/local/lib  -lkyotocabinet -llzo2 -lz -lstdc++ -lrt
-lpthread -lm -lc
/usr/lib/crt1.o(.text+0xa3): In function `_start1':
: undefined reference to `main'
*** Error code 1

Stop in /home/hoge/kyotocabinet-1.2.65.

あれ?ソースファイルもオブジェクトファイルも指定されていない...

 $(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) $(CMDLDFLAGS) -lkyotocabinet $(CMDLIBS)

↑この辺か...おかしいな,マニュアルには

.TARGET The name of the target; also known as ‘@’.

The shorter forms ‘@’, ‘!’, ‘<’, ‘%’, ‘?’, ‘>’, and ‘*’ are permitted for
backward compatibility and are not recommended.

推奨されていないけど互換性のために$<も使えるって書いているんですけどねぇ.

all: TestMake
        echo $<

こんなファイルをファイル名TestMakeとして作って試してみる.

> make -f TestMake
echo

> gmake -f TestMake
echo TestMake
TestMake

やっぱ$<が使えないや...しゃーないので,gmakeで.

> gmake
g++ -march=native -g -O2 -Wall -fPIC -fsigned-char -g0 -O2 -o kcutiltest kcutiltest.o -L. -L/usr/local/lib -L/usr/local/lib  -lkyotocabinet -llzo2 -lz -lstdc++ -lrt -lpthread -lm -lc
(中略)
#================================================================
# Ready to install.
#================================================================
> su
# make install
(中略)
#================================================================
# Thanks for using Kyoto Cabinet.
#================================================================

それでは,LevelDB対Kyoto Cabinetを!

まずはKey-ValueValueが10バイトの短い例を.
Valueがセッションのハッシュ値とか,本当にキャッシュとして使う場合.

LevelDBが速いようです.
もっとも,Kyoto Cabinetの方が圧倒的に機能豊富で現時点で使えているのは事実です.
KCのMapReduce機能は速くて気に入っています.

次にValueの長さが100バイトの例を.

Kyoto Cabinetは書き込みがシングルスレッド,マルチスレッドと試し,LevelDBは書き込みはシングルスレッドのみ(読み込みは,全てのケースでマルチスレッド)ですが,LevelDBが圧勝でした.

ところが,Valueの長さが1000バイトになると,Kyoto Cabinetの方が早くなりました.

ここからも,LevelDBがドメイン特化なことが分かります.

Kyoto Cabinetのベンチマークプログラムはこのような感じで,引数でDBの型も変えられるようになっています.ハッシュとかツリーとかディスクとかメモリとか.

#include "basic_header.h"
#include <unistd.h> // for unlink()
#include "kcpolydb.h"
int main(int argc, char *argv[])
{
  int suc = 0, i;
  time_t start, set_end, get_end;
  int n = omp_get_max_threads();
  kyotocabinet::PolyDB  *db = new kyotocabinet::PolyDB();
  if(argc!=2)
  {
    std::cout<<"KC db filename is required"<<std::endl;
    exit(1);
  }
  unlink(argv[1]);
  if (!db->open(argv[1], kyotocabinet::PolyDB::OWRITER | kyotocabinet::PolyDB::OCREATE)) {
    std::cerr << "open error: " << db->error().name() << std::endl;
    exit(1);
  }

  start = time(NULL);
#pragma omp parallel for shared(suc,i, db)
  for(i=0;i<MAX_LOOP;++i) {
    Poco::MD5Engine con;    string key, val;
    set_key_val(con, (int)(i/REP), key, val);
    if(!db->set(key, val)) {
      std::cout<<db->error().name()<<std::endl;
    }else {
      ++suc;
    }
  }
  set_end = time(NULL);
#pragma omp parallel for shared(suc,i, db)
  for(i=0;i<MAX_LOOP;++i) {
    Poco::MD5Engine con;    string key, val, expected_val;
    set_key_val(con, (int)(i/REP), key, expected_val);
    if(!db->get(key, &val) || val != expected_val) {
      cout<<"get: "<<val<<" KC error: "<<db->error().name()<<std::endl;
    }else {
      ++suc;
    }
  }
  //  std::cout<<key<<val<<std::endl;
#include "basic_footer.h"
  delete db;
  return(0);
}

実行はこんな感じで.

> setenv OMP_NUM_THREADS 1 ; rm -fR /var/tmp/testdb.kch ; env LD_LIBRARY_PATH=/usr/local/lib/gcc45/ time ./kc_bench /var/tmp/testdb.kch

そう,見ての通り,.kch(ファイルベースハッシュDB)を使っています.
他のDBについては,また追って検証結果を報告致します.