Last active
December 16, 2015 22:49
-
-
Save qxj/5509787 to your computer and use it in GitHub Desktop.
compare performance between CDS and TDS when multiple-read and one-write
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// -*- mode: c++ -*- | |
// @(#) test_bdb.cpp Time-stamp: <Julian Qian 2013-05-07 11:37:26> | |
// Copyright 2013 Julian Qian | |
// Author: Julian Qian <[email protected]> | |
// 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