Kyoto Tycoon+Kyoto Cabinetオンリーベンチマーク

Kyotoシリーズは,単体で使ってOracle BerkleyDBなんかとの性能差を確かめるのが楽しいのですが,Kyoto Tycoonを使ってみようかという雰囲気が盛り上がっているので,Tycoonならではのベンチマークをしてみました.

以前のベンチマークでは,memcached互換プロトコルでアクセスしていたので,
最速KVS研究:memcached/mdcached/redis/Kyototycoon-Kyotocabinet - なぜか数学者にはワイン好きが多い
今回は専用APIを使いました.

まず,Kyoto Tycoonのプロセスを一つ上げた時と,違うマシンでもう一つ上げてレプリケーションをさせた時では,ほとんど速度は変わりませんでした.
唯一変わったのは,サンプルのLua拡張を通してセカンダリインデックスを付けたりしてアクセスした時です.
topコマンドでCPU負荷を見ていても,Luaを通した場合は明らかに負荷が上がっていました.ただし,テストに使ったのは貧弱なノートPCなので,普通のサーバ機だと吸収できるレベルかと思います.

Luaを呼び出すプログラムは以下のような感じです.

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

#define MAX_LOOP 100000
#define VAL_LEN_TIMES 256
#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;
  time_t start, set_end, get_end;
  int n = omp_get_max_threads();
  RemoteDB pool[n];
  for(i=0;i<n;++i)
  {
    if (!pool[i].open(argv[1]))
    {
       printf("Connection error: %s\n", pool[i].error().name());
       exit(1);
    }
  }
  start = time(NULL);
#pragma omp parallel for shared(suc)
  for(i=0;i<MAX_LOOP;++i)
  {
    MD5_CTX con;
    RemoteDB *conn = &pool[(int)i/(MAX_LOOP/n)];
    char key[33], val[10*VAL_LEN_TIMES+1];
    std::map<std::string, std::string> table, result;
    set_key_val(&con, (int)(i/REP), key, val);
    /* printf("%s:%s\n",key,val); */
    table["id"] = std::string(key);
    table["name"] = std::string(val);
    if (!conn->play_script(std::string("set"), table, &result))
    {
      fprintf(stderr, "set: %s: set error %s\n",key, conn->error().name());
    }else{
#pragma omp atomic
      ++suc;
    }
     if(i%(MAX_LOOP/100) == 0) printf("set: %d\n",i);
  }
  set_end = time(NULL);
  printf("try=%d success=%d ratio=%f\n",MAX_LOOP,suc/2,(double)suc/2/MAX_LOOP*100.0);
#pragma omp atomic
        ++suc;
      }else
      {
        fprintf(stderr, "value should be [%s] but returned [%s]\n",
                                   should_be, val);
      }
    }
    if(i%(MAX_LOOP/100) == 0) printf("get: %d\n",i);
  }

  for(i=0;i<n;++i)
  {
    pool[i].close();
  }
  get_end = time(NULL);

  printf("try=%d success=%d ratio=%f\n",MAX_LOOP,suc/2,(double)suc/2/MAX_LOOP*100.0);
  printf("set=%d[sec], get=%d[sec], total=%d[sec]\n",
           set_end-start, get_end-set_end, get_end-start);

  return(0);
}