Skip to content

Instantly share code, notes, and snippets.

@qxj
Last active December 16, 2015 22:49
Show Gist options
  • Save qxj/5509787 to your computer and use it in GitHub Desktop.
Save qxj/5509787 to your computer and use it in GitHub Desktop.
compare performance between CDS and TDS when multiple-read and one-write
// -*- mode: c++ -*-
// @(#) test_bdb.cpp Time-stamp: <Julian Qian 2013-05-07 11:37:26>
// Copyright 2013 Julian Qian
// Author: Julian Qian <junist@gmail.com>
// Version: $Id: test_bdb.cpp,v 0.1 2013-05-02 20:58:38 jqian Exp $
//
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/stat.h> // mkdir
#include <sys/types.h> // mkdir
#include <boost/thread.hpp>
#include <db.h>
#define INIT_DATA_NUM 10000
#define READ_NUM 10000
#define WRITE_NUM 5000
#define READ_THREAD_NUM 10
class TestBdb
{
public:
explicit TestBdb(const char* dir):
dataDir_(dir), env_(NULL), db_(NULL)
{
mkdir(dir, S_IRWXU);
}
virtual ~TestBdb()
{
int ret;
if(db_){
ret = db_->close(db_, 0);
if(ret){
env_->err(env_, ret, "DN->close");
}
}
if(env_){
ret = env_->close(env_, 0);
if(ret){
env_->err(env_, ret, "ENV->close");
}
}
}
int test()
{
boost::thread_group tg;
// read threads
for (int i = 0; i < READ_THREAD_NUM; ++i) {
tg.create_thread(boost::bind(&TestBdb::read, this));
}
// write thread
tg.create_thread(boost::bind(&TestBdb::write, this));
tg.join_all();
return 0;
}
virtual int init() = 0;
virtual int read() = 0;
virtual int write() = 0;
protected:
const char* dataDir_;
DB_ENV* env_;
DB* db_;
};
class TestCds: public TestBdb
{
public:
explicit TestCds(const char* dir):
TestBdb(dir){}
virtual ~TestCds(){}
virtual int init()
{
int ret;
ret = db_env_create(&env_, 0);
if(ret){
fprintf(stderr, "failed to create env\n");
return -1;
}
env_->set_errfile(env_, stderr);
ret = env_->open(env_, dataDir_, DB_CREATE | DB_INIT_MPOOL |
DB_INIT_CDB | DB_THREAD, 0);
if(ret) {
env_->err(env_, ret, "ENV->open: %s", dataDir_);
return -1;
}
ret = db_create(&db_, env_, 0);
if(ret){
env_->err(env_, ret, "db_create");
return -1;
}
db_->set_errfile(db_, stderr);
ret = db_->open(db_, NULL, "test.db", NULL, DB_BTREE, DB_CREATE, 0);
if(ret){
env_->err(env_, ret, "DB->open");
return -1;
}
// init data
int cnt = 0;
srand(time(NULL));
DBT key, val;
int k, v;
for (int i = 0; i < INIT_DATA_NUM; ++i) {
memset(&key, 0, sizeof(key));
memset(&val, 0, sizeof(val));
k = rand() % INIT_DATA_NUM;
v = rand() % INIT_DATA_NUM;
key.data = &k;
key.size = sizeof(int);
val.data = &v;
val.size = sizeof(int);
ret = db_->put(db_, NULL, &key, &val, 0);
if(ret){
db_->err(db_, ret, "DB->put, key: %d", k);
}else{
++ cnt;
}
}
fprintf(stderr, "init %d items into db.\n", cnt);
return 0;
}
virtual int read()
{
DBT key, val;
int k, v;
int ret;
srand(time(NULL));
memset(&key, 0, sizeof(key));
memset(&val, 0, sizeof(val));
key.data = &k;
key.size = sizeof(int);
val.data = &v;
val.ulen = sizeof(int);
val.flags = DB_DBT_USERMEM;
int cnt = 0;
for (int i = 0; i < READ_NUM; ++i) {
k = rand() % INIT_DATA_NUM;
ret = db_->get(db_, NULL, &key, &val, 0);
if(!ret){
++ cnt;
}
}
fprintf(stderr, "read out %d items\n", cnt);
return 0;
}
virtual int write()
{
srand(time(NULL));
DBT key, val;
int k, v;
DBC* cur;
int ret;
memset(&key, 0, sizeof(key));
memset(&val, 0, sizeof(val));
key.data = &k;
key.size = sizeof(int);
val.data = &v;
val.size = sizeof(int);
int cnt = 0;
for (int i = 0; i < WRITE_NUM; ++i) {
k = rand() % INIT_DATA_NUM;
v = rand() % INIT_DATA_NUM;
ret = db_->cursor(db_, NULL, &cur, DB_WRITECURSOR);
if(ret){
db_->err(db_, ret, "DB->cursor");
continue;
}
ret = cur->put(cur, &key, &val, DB_KEYFIRST);
if(ret){
db_->err(db_, ret, "DB->put");
}else{
++ cnt;
}
cur->close(cur);
}
fprintf(stderr, "write into %d items\n", cnt);
return 0;
}
};
class TestTds: public TestBdb
{
public:
explicit TestTds(const char* dir):
TestBdb(dir) {}
virtual ~TestTds() {}
virtual int init()
{
int ret;
ret = db_env_create(&env_, 0);
if(ret){
fprintf(stderr, "failed to create env\n");
return -1;
}
env_->set_errfile(env_, stderr);
ret = env_->open(env_, dataDir_, DB_CREATE | DB_INIT_MPOOL |
DB_INIT_LOCK | DB_INIT_TXN | DB_INIT_LOG | DB_THREAD, 0);
if(ret) {
env_->err(env_, ret, "ENV->open: %s", dataDir_);
return -1;
}
ret = db_create(&db_, env_, 0);
if(ret){
env_->err(env_, ret, "db_create");
return -1;
}
db_->set_errfile(db_, stderr);
DB_TXN *txn;
ret = env_->txn_begin(env_, NULL, &txn, 0);
if(ret){
env_->err(env_, ret, "txn_begin");
return -1;
}
ret = db_->open(db_, txn, "test.db", NULL, DB_BTREE, DB_CREATE, 0);
if(ret){
env_->err(env_, ret, "DB->open");
txn->abort(txn);
return -1;
}
txn->commit(txn, 0);
// init data
int cnt = 0;
srand(time(NULL));
DBT key, val;
int k, v;
for (int i = 0; i < INIT_DATA_NUM; ++i) {
memset(&key, 0, sizeof(key));
memset(&val, 0, sizeof(val));
k = rand() % INIT_DATA_NUM;
v = rand() % INIT_DATA_NUM;
key.data = &k;
key.size = sizeof(int);
val.data = &v;
val.size = sizeof(int);
ret = env_->txn_begin(env_, NULL, &txn, 0);
if(ret){
env_->err(env_, ret, "txn_begin");
}else{
ret = db_->put(db_, txn, &key, &val, 0);
if(ret){
db_->err(db_, ret, "DB->put, key: %d", k);
txn->abort(txn);
}else{
ret = txn->commit(txn, 0);
if(ret){
txn->abort(txn);
env_->err(env_, ret, "commit");
}else{
++ cnt;
}
}
}
}
fprintf(stderr, "init %d items into db.\n", cnt);
return 0;
}
virtual int read()
{
DBT key, val;
int k, v;
int ret;
srand(time(NULL));
memset(&key, 0, sizeof(key));
memset(&val, 0, sizeof(val));
key.data = &k;
key.size = sizeof(int);
val.data = &v;
val.ulen = sizeof(int);
val.flags = DB_DBT_USERMEM;
int cnt = 0;
for (int i = 0; i < READ_NUM; ++i) {
k = rand() % INIT_DATA_NUM;
DB_TXN *txn;
ret = env_->txn_begin(env_, NULL, &txn, 0);
if(ret != 0) {
env_->err(env_, ret, "txn_begin");
continue;
}
ret = db_->get(db_, txn, &key, &val, 0);
if(!ret){
++ cnt;
}
ret = txn->abort(txn);
}
fprintf(stderr, "read out %d items\n", cnt);
return 0;
}
virtual int write()
{
srand(time(NULL));
DBT key, val;
int k, v;
int ret;
memset(&key, 0, sizeof(key));
memset(&val, 0, sizeof(val));
key.data = &k;
key.size = sizeof(int);
val.data = &v;
val.size = sizeof(int);
int cnt = 0;
for (int i = 0; i < WRITE_NUM; ++i) {
k = rand() % INIT_DATA_NUM;
v = rand() % INIT_DATA_NUM;
DB_TXN *txn;
ret = env_->txn_begin(env_, NULL, &txn, 0);
if(ret != 0) {
env_->err(env_, ret, "txn_begin");
}else{
ret = db_->put(db_, txn, &key, &val, 0);
if(ret){
db_->err(db_, ret, "DB->put, key: %d", k);
txn->abort(txn);
}else{
ret = txn->commit(txn, 0);
if(ret){
txn->abort(txn);
env_->err(env_, ret, "commit");
}else{
++ cnt;
}
}
}
}
fprintf(stderr, "write into %d items\n", cnt);
return 0;
}
};
int main(int argc, char *argv[])
{
if(argc == 1){
printf("%s <cds/tds>\n", argv[0]);
return 0;
}
TestBdb *bdb;
if(strcmp(argv[1], "cds") == 0){
bdb = new TestCds("./cds");
}else{
bdb = new TestTds("./tds");
}
if(bdb->init()){
fprintf(stderr, "failed to init db\n");
}else{
struct timeval start, end;
gettimeofday(&start, NULL);
bdb->test();
gettimeofday(&end, NULL);
fprintf(stderr, "time cost: %.6f s.\n", (end.tv_sec - start.tv_sec) + (double) (end.tv_usec - start.tv_usec) / 1000000 );
}
delete bdb;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment