BerkeleyDB和eXtremeDB性能在LINUX下的比较
1、BerkeleyDB测试源程序:
#include <sys/types.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef _WIN32
extern int getopt(int, char * const *, const char *);
#else
#include <unistd.h>
#endif
#include "db.h"
extern void __os_clock __P((DB_ENV *, u_int32_t *, u_int32_t *));
void usage __P((void));
struct db_time {
u_int32_t secs, usecs;
};
struct db_time start_time, end_time;
u_int32_t pagesize = 32 * 1024;
u_int bulkbufsize = 4 * 1024 * 1024;
u_int logbufsize = 8 * 1024 * 1024;
u_int cachesize = 32 * 1024 * 1024;
u_int datasize = 32;
u_int keysize = 8;
u_int numitems = 0;
FILE *fp;
char *progname;
void op_ds(u_int, int);
void op_ds_bulk(u_int, u_int *);
void op_tds(u_int, int, u_int32_t);
void res(char *, u_int);
void
res(char *msg, u_int ops)
{
double elapsed;
struct db_time v;
v.secs = end_time.secs - start_time.secs;
v.usecs = end_time.usecs - start_time.usecs;
if (start_time.usecs > end_time.usecs) {
v.secs--;
v.usecs += 1000000;
}
elapsed = v.secs + v.usecs / 1e6;
printf("%s
\telapsed time: %f seconds : %g key/data pairs per sec
",
msg, elapsed, ops / elapsed);
}
void
op_ds(u_int ops, int update)
{
char *letters = "abcdefghijklmnopqrstuvwxuz";
DB *dbp;
DBT key, data;
char *keybuf, *databuf;
DB_MPOOL_STAT *gsp;
(void)remove("a");
assert((keybuf = malloc(keysize)) != NULL);
assert((databuf = malloc(datasize)) != NULL);
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
key.data = keybuf;
key.size = keysize;
memset(keybuf, 'a', keysize);
data.data = databuf;
data.size = datasize;
memset(databuf, 'b', datasize);
assert(db_create(&dbp, NULL, 0) == 0);
dbp->set_errfile(dbp, stderr);
assert(dbp->set_pagesize(dbp, pagesize) == 0);
assert(dbp->open(dbp, NULL, NULL, NULL, DB_BTREE, DB_CREATE, 0666) == 0);
dbp->dbenv->memp_stat(dbp->dbenv, &gsp, NULL, DB_STAT_CLEAR);
if (update) {
__os_clock(NULL, &start_time.secs, &start_time.usecs);
for (; ops > 0; --ops) {
keybuf[(ops % keysize)] = letters[(ops % 26)];
assert(dbp->put(dbp, NULL, &key, &data, 0) == 0);
}
__os_clock(NULL, &end_time.secs, &end_time.usecs);
} else {
assert(dbp->put(dbp, NULL, &key, &data, 0) == 0);
__os_clock(NULL, &start_time.secs, &start_time.usecs);
for (; ops > 0; --ops)
assert(dbp->get(dbp, NULL, &key, &data, 0) == 0);
__os_clock(NULL, &end_time.secs, &end_time.usecs);
}
dbp->dbenv->memp_stat(dbp->dbenv, &gsp, NULL, 0);
assert(gsp->st_cache_miss == 0);
assert(dbp->close(dbp, 0) == 0);
}
void
op_ds_bulk(u_int ops, u_int *totalp)
{
DB *dbp;
DBC *dbc;
DBT key, data;
u_int32_t len, klen;
u_int i, total;
char *keybuf, *databuf;
void *pointer, *dp, *kp;
DB_MPOOL_STAT *gsp;
(void)remove("a");
assert((keybuf = malloc(keysize)) != NULL);
assert((databuf = malloc(bulkbufsize)) != NULL);
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
key.data = keybuf;
key.size = keysize;
data.data = databuf;
data.size = datasize;
memset(databuf, 'b', datasize);
assert(db_create(&dbp, NULL, 0) == 0);
dbp->set_errfile(dbp, stderr);
assert(dbp->set_pagesize(dbp, pagesize) == 0);
assert(dbp->set_cachesize(dbp, 0, cachesize, 1) == 0);
assert(dbp->open(dbp, NULL, NULL, NULL, DB_BTREE, DB_CREATE, 0666) == 0);
for (i = 1; i <= numitems; ++i) {
(void)sprintf(keybuf, "%10d", i);
assert(dbp->put(dbp, NULL, &key, &data, 0) == 0);
}
#if 0
fp = fopen("before", "w"); dbp->set_msgfile(dbp, fp);
assert (dbp->stat_print(dbp, DB_STAT_ALL) == 0);
#endif
assert(dbp->cursor(dbp, NULL, &dbc, 0) == 0);
data.ulen = bulkbufsize;
data.flags = DB_DBT_USERMEM;
dbp->dbenv->memp_stat(dbp->dbenv, &gsp, NULL, DB_STAT_CLEAR);
if (ops > 10000)
ops = 10000;
__os_clock(NULL, &start_time.secs, &start_time.usecs);
for (total = 0; ops > 0; --ops) {
assert(dbc->c_get(
dbc, &key, &data, DB_FIRST | DB_MULTIPLE_KEY) == 0);
DB_MULTIPLE_INIT(pointer, &data);
while (pointer != NULL) {
DB_MULTIPLE_KEY_NEXT(pointer, &data, kp, klen, dp, len);
if (kp != NULL)
++total;
}
}
__os_clock(NULL, &end_time.secs, &end_time.usecs);
*totalp = total;
dbp->dbenv->memp_stat(dbp->dbenv, &gsp, NULL, 0);
assert(gsp->st_cache_miss == 0);
#if 0
fp = fopen("before", "w"); dbp->set_msgfile(dbp, fp);
assert (dbp->stat_print(dbp, DB_STAT_ALL) == 0);
#endif
/*assert(dbp->close(dbp, 0) == 0);*/
}
void
op_tds(u_int ops, int update, u_int32_t txn_flags)
{
DB *dbp;
DBT key, data;
DB_ENV *dbenv;
DB_TXN *txn;
char *keybuf, *databuf;
DB_MPOOL_STAT *gsp;
#ifndef _WIN32
(void)system("rm -rf TESTDIR; mkdir TESTDIR");
#endif
assert((keybuf = malloc(keysize)) != NULL);
assert((databuf = malloc(datasize)) != NULL);
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
key.data = keybuf;
key.size = keysize;
memset(keybuf, 'a', keysize);
data.data = databuf;
data.size = datasize;
memset(databuf, 'b', datasize);
assert(db_env_create(&dbenv, 0) == 0);
dbenv->set_errfile(dbenv, stderr);
assert(dbenv->set_flags(dbenv, DB_AUTO_COMMIT | txn_flags, 1) == 0);
assert(dbenv->set_lg_bsize(dbenv, logbufsize) == 0);
assert(dbenv->open(dbenv, "TESTDIR",
DB_CREATE | DB_PRIVATE | DB_INIT_LOCK |
DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN,
0666) == 0);
assert(db_create(&dbp, dbenv, 0) == 0);
assert(dbp->set_pagesize(dbp, pagesize) == 0);
assert(dbp->open(dbp, NULL, "a",
NULL, DB_BTREE, DB_CREATE, 0666) == 0);
if (update) {
dbenv->memp_stat(dbenv, &gsp, NULL, DB_STAT_CLEAR);
__os_clock(NULL, &start_time.secs, &start_time.usecs);
for (; ops > 0; --ops){
assert(dbenv->txn_begin(dbenv, NULL, &txn, 0) == 0);
assert(dbp->put(dbp, NULL, &key, &data, 0) == 0);
assert(txn->commit(txn, 0) == 0);
}
__os_clock(NULL, &end_time.secs, &end_time.usecs);
dbenv->memp_stat(dbenv, &gsp, NULL, 0);
assert(gsp->st_page_out == 0);
} else {
assert(dbp->put(dbp, NULL, &key, &data, 0) == 0);
dbenv->memp_stat(dbenv, &gsp, NULL, DB_STAT_CLEAR);
__os_clock(NULL, &start_time.secs, &start_time.usecs);
for (; ops > 0; --ops) {
assert(dbenv->txn_begin(dbenv, NULL, &txn, 0) == 0);
assert(dbp->get(dbp, NULL, &key, &data, 0) == 0);
assert(txn->commit(txn, 0) == 0);
}
__os_clock(NULL, &end_time.secs, &end_time.usecs);
dbenv->memp_stat(dbenv, &gsp, NULL, 0);
assert(gsp->st_cache_miss == 0);
}
assert(dbp->close(dbp, 0) == 0);
assert(dbenv->close(dbenv, 0) == 0);
}
int
main(int argc, char *argv[])
{
extern char *optarg;
extern int optind;
u_int ops, total;
int ch;
int major, minor, patch;
if ((progname = strrchr(argv[0], '/')) == NULL)
progname = argv[0];
else
++progname;
ops = 100000;
while ((ch = getopt(argc, argv, "d:k:o:p:")) != EOF)
switch (ch) {
case 'd':
datasize = (u_int)atoi(optarg);
break;
case 'k':
keysize = (u_int)atoi(optarg);
break;
case 'o':
ops = (u_int)atoi(optarg);
break;
case 'p':
pagesize = (u_int32_t)atoi(optarg);
break;
case '?':
default:
usage();
}
argc -= optind;
argv += optind;
numitems = (cachesize / (keysize + datasize - 1)) / 2;
db_version(&major, &minor, &patch);
printf("Using Berkeley DB %d.%d.%d - ", major, minor, patch);
printf("ops: %u; keysize: %d; datasize: %d
", ops, keysize, datasize);
op_ds(ops, 0);
res("DS (read):", ops);
if (keysize >= 8) {
op_ds_bulk(ops, &total);
res("DS (bulk read):", total);
} else {
printf("DS (bulk read):
");
printf("\tskipped: bulk get requires a key size >= 10
");
}
op_ds(ops, 1);
res("DS (write):", ops);
op_tds(ops, 0, 0);
res("TDS (read):", ops);
op_tds(ops, 1, DB_LOG_INMEMORY);
res("TDS (write, in-memory logging):", ops);
op_tds(ops, 1, DB_TXN_NOSYNC);
res("TDS (write, no-sync on commit):", ops);
op_tds(ops, 1, DB_TXN_WRITE_NOSYNC);
res("TDS (write, write-no-sync on commit):", ops);
op_tds(ops, 1, 0);
res("TDS (write, sync on commit):", ops);
return (EXIT_SUCCESS);
}
void
usage()
{
fprintf(stderr,
"usage: %s [-d datasize] [-k keysize] [-o ops] [-p pagesize]
",
progname);
exit(1);
}
2、eXtremeDB测试源程序:
/*****************************************************************
* *
* Copyright (c) 2001-2006 McObject LLC. All Right Reserved. *
* *
*****************************************************************/
/* This test allows to receive some results about the eXtremeDB performance
* for all basic operations. This test inserts N objects into a class, creating
* a hash index as it does insertions; then separatelly builds a tree index,
* performs searches using a tree and a hash table, an a sequential search.
* At last the tree is removed and all the object are deleted one-by-one.
* Each Insetrtion and deletion done in a separate transaction, so the
* commit time is included in the measurements.
*/
#include <platform.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#include <mcoHA.h>
#include "perf2.h"
/* Make sure you've got this 16M, otherwise you'll be measuring
* the performance of your disk.
*/
#define DBSIZE ( 1024 * 16000 )
#define PAGESIZE 128
const int MAP_ADDRESS = 0x20000000;
/* If you change the number of objects inserted, make sure that you
* first have enough memory (DBSIZE), and also decalred hash table
* size appropriatelly (hkey[estimated_numeber_of_entries] in perf2.mco
*/
const int nRecords = 100000;
void _SH_(void) {
char text[] = {
"
This test allows to receive some results about the eXtremeDB
"
"performance for all basic operations. This test inserts N objects
"
"into a class, creating a hash index as it does insertions; then
"
"separatelly builds a tree index,performs searches using a tree and
"
"a hash table, an a sequential search.At last the tree is removed
"
"and all the object are deleted one-by-one. Each insertion and deletion
"
"done in a separate transaction, so the commit time is included in the
"
"measurements.
"
};
char text1[] = {
"Copyright (c) 2001-2006 McObject LLC. All Right Reserved.
"
};
printf("%s
eXtremeDB runtime version %d.%d, build %d
%s
Press Enter to start",
text, MCO_COMP_VER_MAJOR, MCO_COMP_VER_MINOR, MCO_COMP_BUILD_NUM,text1);
getchar();
}
static void errhandler( int n ) {
printf( "
eXtremeDB runtime fatal error: %d", n );
getchar();
exit( -1 );
}
int main( void ) {
const char *dbName = "perf2";
time_t start_time;
MCO_RET rc;
mco_db_h db = 0;
mco_trans_h t;
int i;
long n = 0;
Record rec;
mco_cursor_t c;
uint4 key = 1999;
void *start_mem;
mco_runtime_info_t info;
_SH_();
mco_get_runtime_info( &info);
if ( info.mco_shm_supported ) {
start_mem = (void*)MAP_ADDRESS;
}
else {
start_mem = (void*)malloc(DBSIZE);
if (!start_mem) {
printf("Couldn't allocated memory
");
exit (1);
}
};
mco_error_set_handler( &errhandler );
rc= mco_runtime_start();
rc = mco_db_open( dbName, perf2_get_dictionary(), start_mem, DBSIZE, (uint2) PAGESIZE );
if ( rc ) {
printf( "
error %d creating database", rc );
if ( !info.mco_shm_supported )
free( start_mem );
exit( 1);
}
/* connect to the database, obtain a database handle */
mco_db_connect( dbName, &db );
/* insert Records, don't create the tree index yet
*/
printf("Insert ");
Sleep(20);
start_time = msec();
for (i=0; i < nRecords; i++) {
key = (3141592621u*i + 2718281829u) % 1000000007u;
rc = mco_trans_start( db, MCO_READ_WRITE, MCO_TRANS_FOREGROUND, &t );
if( MCO_S_OK != rc )
exit(1);
rc = Record_new(t, &rec);
Record_key_put(&rec, key);
rc = mco_trans_commit(t);
if (!rc ) n++;
if (i%(nRecords/10)==0)
printf (".");
}
printf(" %d objects: %d milliseconds,(%d microsecs/object)
",
n, (int)(msec() - start_time), ((msec() - start_time) * 1000)/n);
/* create the tree index */
Sleep(20);
rc = mco_trans_start( db, MCO_READ_WRITE, MCO_TRANS_FOREGROUND, &t );
if( MCO_S_OK != rc ) {
if ( !info.mco_shm_supported )
free( start_mem );
exit(1);
};
printf("Creating tree ...... ");
start_time = msec();
Record_tkey_create (t);
mco_trans_commit(t);
printf(" %d objects: %d milliseconds (%d microsecs/object)
",
nRecords, (int)(msec() - start_time ), ((msec() - start_time) * 1000)/nRecords);
/* hash search */
Sleep(20);
rc = mco_trans_start( db, MCO_READ_ONLY, MCO_TRANS_FOREGROUND, &t );
if( MCO_S_OK != rc ) {
if ( !info.mco_shm_supported )
free( start_mem );
exit(1);
};
printf("Hash search ");
start_time = msec();
for (i=0; i < nRecords; i++) {
key = (3141592621u*i + 2718281829u) % 1000000007u;
rc = Record_hkey_find(t, key, &rec);
if (i%(nRecords/10)==0)
printf (".");
}
printf("% d searches: %d milliseconds (%d microsecs/search)
",
nRecords, (int)(msec() - start_time ), ((msec() - start_time) * 1000)/nRecords);
mco_trans_commit(t);
/* tree search */
Sleep(20);
printf("Tree search ");
start_time = msec();
rc = mco_trans_start( db, MCO_READ_ONLY, MCO_TRANS_FOREGROUND, &t );
Record_tkey_index_cursor(t, &c );
for (i=0; i < nRecords; i++) {
key = (3141592621u*i + 2718281829u) % 1000000007u;
Record_tkey_search( t, &c, MCO_EQ, key );
if (i%(nRecords/10)==0)
printf (".");
}
printf(" %d searches: %d milliseconds (%d microsecs/search)
",
nRecords, (int)(msec() - start_time ), ((msec() - start_time) * 1000)/nRecords);
mco_trans_commit(t);
/* cursor movements */
Sleep(20);
printf("Sequential ");
start_time=msec();
rc = mco_trans_start( db, MCO_READ_ONLY, MCO_TRANS_FOREGROUND, &t );
Record_tkey_index_cursor(t, &c );
for (n = 0,rc = mco_cursor_first(t, &c); rc == MCO_S_OK; rc = mco_cursor_next(t, &c)) {
if (n%(nRecords/10)==0)
printf (".");
n++;
}
printf(" %d searches: %d milliseconds (%d microsecs/search)
",
n, (int)(msec() - start_time ), ((msec() - start_time) * 1000)/n);
mco_trans_commit(t);
/* removing the tree */
rc = mco_trans_start( db, MCO_READ_WRITE, MCO_TRANS_FOREGROUND, &t );
if( MCO_S_OK != rc ) {
if ( !info.mco_shm_supported )
free( start_mem );
exit(1);
};
printf("Removing the tree ...... ");
start_time = msec();
Record_tkey_drop (t);
mco_trans_commit(t);
printf(" %d milliseconds
", (int)(msec() - start_time ));
/* Search using hash index and remove the object ones found
*/
printf("Search/delete ");
start_time = msec();
for (n=0,i=0; i < nRecords; i++) {
key = (3141592621u*i + 2718281829u) % 1000000007u;
rc = mco_trans_start( db, MCO_READ_WRITE, MCO_TRANS_FOREGROUND, &t );
if( MCO_S_OK != rc ) exit(1);
rc = Record_hkey_find(t, key, &rec);
rc = Record_delete(&rec);
rc = mco_trans_commit(t);
if (!rc) n++;
if (n%(nRecords/10)==0)
printf (".");
}
printf(" %d objects: %d milliseconds (%d microsecs/object)
",
n, (int)(msec() - start_time ), ((msec() - start_time) * 1000)/n);
/* disconnect from the database, db is no longer valid */
mco_db_disconnect( db );
/* destroy the database */
mco_db_close( dbName );
mco_runtime_stop();
if ( !info.mco_shm_supported )
free( start_mem );
printf( "
Press Enter to exit" );
getchar();
PROG_EXIT(0);
}
其数据库为:
/*****************************************************************
* *
* Copyright (c) 2001-2006 McObject LLC. All Right Reserved. *
* *
*****************************************************************/
#define int1 signed<1>
#define int2 signed<2>
#define int4 signed<4>
#define uint8 unsigned<8>
#define uint4 unsigned<4>
#define uint2 unsigned<2>
#define uint1 unsigned<1>
declare database perf2;
class Record
{
uint4 key;
hash <key> hkey[100000];
voluntary tree <key> tkey;
};
3、测试结果为:(无法上传,请查看原文:))
一、BerkeleyDB:
二、eXtremeDB: