最新Kyoto Tycoonベンチマーク

こちらでKyoto Tycoonが宣伝されていて,再び試してみることにしました.
Kyoto Tycoon 0.9.24 Released: Featuring Auto... • myNoSQL

New release for Kyoto Tycoon ― the Tokyo Tyrant Plus Plus:

Kyoto Tycoon 0.9.24 has been released. It features “auto snapshot” for on-memory databases, inspired by Redis’s snapshot mechanism.

おおお,memcachedプロトコルの可能性
http://fallabs.com/mikio/tech/promenade.cgi?id=112

高効率キャッシュサーバ兼データベースサーバであるKyoto Tycoonのネットワーク通信機構をプラグインで切り替えられるようにして、memcachedプロトコルにも対応したというお話。

http://fallabs.com/mikio/tech/promenade.cgi?id=122

ついでに、スナップショットをオンザフライで圧縮する機能もつけてみた。CPU時間はよりたくさん使うが、子プロセスがやるんで完全に並列化されるはずで、CPUコアが多い場合にはディスクアクセスを減らせる分だけお得な気がする。サポートされる圧縮アルゴリズムはKCをビルドした際に決まり、通常はzlibだけ組み込まれる。LZOとLZMAもオプションで組み込める。

これはそそられます.

速度自体は一番遅かったKyoto Tycoon+Kyoto Cabinet.
最初に試したときのバージョンは...kyotocabinet-1.2.18+kyototycoon-0.9.3でした.
最速KVS研究第一弾(memcached/Tokyo Tyrant/Kyoto Tycoon) - なぜか数学者にはワイン好きが多い


色々試したいので,圧縮ライブラリも全部入れます.

> wget http://www.oberhumer.com/opensource/lzo/download/lzo-2.04.tar.gz
> tar xvf lzo-2.04.tar.gz
> cd lzo-2.04
> ./configure
> make
> su
# make install
> wget http://tukaani.org/lzma/lzma-4.32.7.tar.gz
> tar xvf lzma-4.32.7.tar.gz
> cd lzma-4.32.7
> ./configure
> make
> su
# make install

そしてKyoto Cabinetも新しいのを入れます.

> wget http://fallabs.com/kyotocabinet/pkg/kyotocabinet-1.2.34.tar.gz
> tar xvf kyotocabinet-1.2.34.tar.gz
> cd kyotocabinet-1.2.34
> ./configure --enable-lzo --enable-lzma
> make

/usr/lib/crt1.o(.text+0xa3): In function `_start1':
: undefined reference to `main'
./libkyotocabinet.so: undefined reference to `__sync_bool_compare_and_swap_8'
./libkyotocabinet.so: undefined reference to `__sync_lock_test_and_set_8'
./libkyotocabinet.so: undefined reference to `__sync_fetch_and_add_8'
*** Error code 1

Stop in /usr/home/tetu-s/kyotocabinet-1.2.34.

ありゃ,これはなんだろう...と思ってエラーメッセージでググったら,自分のページがひっかかった...小人さん,ありがとう.

ついにKyoto Cabinet/Kyoto Tycoon試してみた - なぜか数学者にはワイン好きが多い

おっと.この手のエラーはFreeBSD用になっていないのが原因で,次のようにコンパイルするのが正解.

その通りにやってみます.

> setenv CPPFLAGS "-march=i686"
> ./configure --enable-lzo --enable-lzma
> make

/usr/lib/crt1.o(.text+0xa3): In function `_start1':
: undefined reference to `main'
*** Error code 1

Stop in /usr/home/tetu-s/kyotocabinet-1.2.34.

あ,これも毎度の...FreeBSDのせい...これはmakeじゃなくてgmakeを使えば大丈夫なので,linuxだと起こらないトラブルなのでしょう.

> gmake
> su
# make install

そして最新のKyoto Tycoonをインストール.

> wget http://fallabs.com/kyototycoon/pkg/kyototycoon-0.9.25.tar.gz
> tar xvf kyototycoon-0.9.25.tar.gz
> cd kyototycoon-0.9.25
> env CPPFLAGS="-I/usr/local/include/lua51" LDFLAGS="-L/usr/local/lib/lua51" ./configure --enable-lua
> gmake
> su
# make install

では,同じベンチマークでKyoto Tycoonの0.9.3と0.9.25を比較してみます.
使ったプログラムは前回と同じで,POCO++を使ってます.

#include <sstream>
#include <iostream>
#include <Poco/Net/HTTPClientSession.h>
#include <Poco/Net/StreamSocket.h>
#include <Poco/Net/SocketAddress.h>
#include <Poco/Net/HTTPRequest.h>
#include <Poco/Net/HTTPResponse.h>

using namespace std;
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <md5.h>
#include <omp.h>

#define MAX_LOOP 1000
#define VAL_LEN_TIMES 10
#define REP 10
void set_key_val(MD5_CTX *con, int seed, char *key, char *val)
{
  sprintf(key,"stress-test-%010d",seed);
  for(int i=0;i<VAL_LEN_TIMES;++i)
  {
    sprintf(val+i*10,"%010d",seed);
  }
  MD5Init(con);
  MD5Update(con, key, strlen(key));
  MD5End(con, key);
}
int main(int argc, char *argv[])
{
  int suc = 0, i;
  int n = omp_get_max_threads();
  Poco::Net::HTTPClientSession **pool
    = (Poco::Net::HTTPClientSession **)malloc(sizeof(Poco::Net::HTTPClientSession *)*n);
  for(int i=0;i<n;++i)
  {
    Poco::Net::StreamSocket *soc = new Poco::Net::StreamSocket;
    Poco::Net::HTTPClientSession *client = new Poco::Net::HTTPClientSession(*soc);
    client->setHost(argv[1]);
    client->setPort(1978);
    pool[i] = client;
  }
#pragma omp parallel for shared(suc,i)
  for(i=0;i<MAX_LOOP;++i)
  {
    Poco::Net::HTTPClientSession client = pool[(int)i/(MAX_LOOP/n)];
    MD5_CTX con;
    char key[33], val[10*VAL_LEN_TIMES+1];
    set_key_val(&con, (int)(i/REP), key, val);
    Poco::Net::HTTPResponse response;
    Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_POST, "/rpc/set",Poco::Net::HTTPMessage::HTTP_1_1);
    client.setKeepAlive(true);
    request.setContentType("text/tab-separated-values");
    request.setHost(client.getHost(), client.getPort());
    request.setContentLength(strlen(key)+strlen(val)+12);
    ostream &req = client.sendRequest(request);

    req <<"key\t"<<key<<"\n";
    req <<"value\t"<<val<<"\n";
    istream &res =  client.receiveResponse(response);
    int len = response.getContentLength();
    char *resbody = new char[len+1];
    res.read(resbody,len);
    if (response.getStatus() != Poco::Net::HTTPResponse::HTTP_OK)
    {
      fprintf(stderr, "set: %s: kyoto error %s[%s] status=%03d",
            key, resbody, response.getReason().c_str(),
            response.getStatus());
      fprintf(stderr, "\n");
    }else
    {
      ++suc;
    }
    soc.shutdown();

    delete[] resbody;
  }
#pragma omp parallel for
  for(i=0;i<MAX_LOOP;++i)
  {
    Poco::Net::HTTPClientSession client(argv[1],11211);
    MD5_CTX con;
    char key[33], val[10*VAL_LEN_TIMES+1];
    set_key_val(&con, (int)(i/REP), key, val);
    Poco::Net::HTTPResponse response;
    Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_POST, "/rpc/get",Poco::Net::HTTPMessage::HTTP_1_1);
    client.setKeepAlive(true);
    request.setContentType("text/tab-separated-values");
    request.setHost(client.getHost(), client.getPort());
    request.setContentLength(strlen(key)+5);
    ostream &req = client.sendRequest(request);
    req <<"key\t"<<key<<"\n";

    istream &res =  client.receiveResponse(response);
    int len = response.getContentLength();
    char *resbody = new char[len+1];
     res.read(resbody,len);
    *(resbody+len) = '\0';
     if (response.getStatus() != Poco::Net::HTTPResponse::HTTP_OK)
    {
      fprintf(stderr, "get: %s: kyoto error %s[%s] status=%03d",
            key, resbody, response.getReason().c_str(),
            response.getStatus());
      fprintf(stderr, "\n");
    }else
    {
      ++suc;
    }
    delete[] resbody;
  }

  printf("try=%d success=%d ratio=%f\n",MAX_LOOP,suc/2,(double)suc/2/MAX_LOOP*100.0);
  return(0);
}

結果...最新の方が遅くなりました.

詳しく見ると,最新の0.9.25のsetが遅くなってますね.何かデフォルト値が変わったのか,バグ取りをした結果遅くなったのかはまだ調べていません.
バイナリプロトコルだとnoreplyモードもあるようなので,ぜひ試してみたいです.
http://fallabs.com/mikio/tech/promenade.cgi?id=120