最近tokyocabinet這個(gè)數(shù)據(jù)庫(kù)很流行,網(wǎng)上出現(xiàn)很多研究這個(gè)玩意兒的文章。在它的
主頁(yè)上,給出的
benchmark表明,在它的硬件環(huán)境下,插入一百萬數(shù)據(jù)僅需不到一秒的時(shí)間。
我被震撼了,為了親眼所見,也為了和我之前寫的
commoncache庫(kù)進(jìn)行比較,我決定在我自己的機(jī)器上,使用同樣類型,大小的數(shù)據(jù),同樣的量級(jí),進(jìn)行插入數(shù)據(jù)這個(gè)操作的比較。
下面給出我寫的測(cè)試文件:
針對(duì)tokyocabinet的:
test_unfix_cache.c
/********************************************************************
created: 2008/05/30
filename: test_unfix_cache.c
author: Lichuang
purpose:
*********************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <signal.h>
#include <arpa/inet.h>
#include <tcutil.h>
#include <tchdb.h>
TCHDB *hdb = NULL;
void mainloop();
void createrandstring(char* string, int len);
int isparent = 0;
int main()
{
hdb = tchdbnew();
if (!hdb)
{
printf("create error!\n");
exit(-1);
}
if (!tchdbopen(hdb, "1.hdb", HDBOWRITER | HDBOCREAT))
{
printf("open error!\n");
exit(-1);
}
mainloop();
return 0;
}
#define STRING_LEN 5
void mainloop()
{
char string[STRING_LEN];
int num, i, len;
srand((unsigned)time(NULL) + getpid());
len = STRING_LEN - 1;
for (i = 1; i < 1000000; ++i)
{
memset(string, 0, STRING_LEN);
createrandstring(string, len);
if (!tchdbput2(hdb, string, string))
{
}
else
{
}
}
printf("pid = %d, test done\n", getpid());
}
const char str[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
void createrandstring(char* string, int len)
{
int x, i;
for (i = 0; i < len - 1; ++i)
{
x = rand() % (sizeof(str) - 1);
//x = (i + len) % (sizeof(str) - 1);
string[i] = str[x];
}
string[++i] = str[len % sizeof(str) + 1];
string[i] = '\0';
}
對(duì)應(yīng)的Makefile:
all:test_unfix_cache.c
gcc -I/usr/local/include test_unfix_cache.c -o test_unfix_cache -L/usr/local/lib -ltokyocabinet -lz -lbz2 -lrt -lpthread -lm -lc
而針對(duì)commoncache的測(cè)試文件是:
/********************************************************************
created: 2008/05/30
filename: test_unfix_cache.c
author: Lichuang
purpose:
*********************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <signal.h>
#include <arpa/inet.h>
#include "ccache.h"
#include "memory.h"
ccache_t* cache;
void mainloop();
void createrandstring(char* string, int len);
int isparent = 0;
int main()
{
cache = ccache_create(75000, 100, "./testunfixmap", 10, 810, 1);
if (NULL == cache)
{
printf("create_cache error!\n");
return -1;
}
mainloop();
return 0;
}
#define STRING_LEN 5
int cmp_fun(const void* data1, const void* data2, int len)
{
return memcmp(data1, data2, sizeof(char) * len);
}
void mainloop()
{
char string[STRING_LEN];
int i, len;
ccache_data_t data;
srand((unsigned)time(NULL) + getpid());
len = STRING_LEN - 1;
for (i = 1; i < 1000000; ++i)
{
memset(string, 0, STRING_LEN);
createrandstring(string, len);
data.datasize = len;
data.keysize = len;
data.data = (void*)&string;
data.key = (void*)&string;
//printf("i = %d\n", i);
if (0 > ccache_insert(&data, cache, cmp_fun, NULL, NULL))
{
}
else
{
continue;
}
}
printf("pid = %d, test done\n", getpid());
}
const char str[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
void createrandstring(char* string, int len)
{
int x, i;
for (i = 0; i < len - 1; ++i)
{
x = rand() % (sizeof(str) - 1);
//x = (i + len) % (sizeof(str) - 1);
string[i] = str[x];
}
string[++i] = str[len % sizeof(str) + 1];
string[i] = '\0';
}
在commoncache的項(xiàng)目代碼的test目錄中,同樣存在一個(gè)名為test_unfix_test.c的文件,是我以前寫commoncache時(shí)測(cè)試用的,不過原來的那個(gè)文件功能較多,不僅有插入操作,還有查找,替換等操作,這次為了測(cè)試,我對(duì)這個(gè)文件進(jìn)行了精簡(jiǎn),只保留插入數(shù)據(jù)操作的部分。使用的是commoncache中的hash-rbtree結(jié)構(gòu)。
性能測(cè)試結(jié)果:
tokyocabinet:
lichuang@lichuang:/media/e/source/tokyocabinet/test$ time ./test_unfix_cache
pid = 15464, test done
real 0m0.373s
user 0m0.364s
sys 0m0.008s
commoncache:
lichuang@lichuang:/media/e/source/ccache/bin$ time ./test_unfix_cache
pid = 15514, test done
real 0m0.235s
user 0m0.228s
sys 0m0.004s
看上來,commoncache比之tokyocabinet還稍好一些?
不過,commoncache與tokyocabinet還是有區(qū)別的,前者工作的區(qū)域是共享內(nèi)存,后者是磁盤文件,有這樣的表現(xiàn),確實(shí)驚人。
這次比較,起碼給了我一些些的自信,我的commoncache不比世界一流的文件數(shù)據(jù)庫(kù)性能差的太多。
下一步,我想繼續(xù)下面的幾個(gè)工作:
1) 國(guó)慶的時(shí)候,整理出一份commoncache的設(shè)計(jì)文檔,算是階段性的一個(gè)小結(jié)。另外,commoncache在插入數(shù)據(jù)的時(shí)候,有時(shí)會(huì)報(bào)錯(cuò),我還得查查是為什么。
2) 抽空要開始研究文件數(shù)據(jù)庫(kù)的實(shí)現(xiàn)了,tokyocabinet就是一個(gè)不錯(cuò)的參考。
另外,多說幾句,一個(gè)產(chǎn)品要成功,僅僅有性能是不夠,可維護(hù)性,可備份性,優(yōu)秀的協(xié)議設(shè)計(jì)等等,都是重要的指標(biāo)。我想,commoncache只做到了性能這一點(diǎn),我需要在其他幾方面繼續(xù)努力。
哦,忘了給出我的環(huán)境參數(shù):
ubuntu9.04,內(nèi)核2.6.18,內(nèi)存3G,intel 雙核CPU。