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-ValueのValueが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については,また追って検証結果を報告致します.