最近tokyocabinet这个数据库很流行,网上出现很多研究这个玩意儿的文章。在它的
主页上,给出的
benchmark表明,在它的硬件环境下,插入一百万数据仅需不到一秒的时间。
我被震撼了,为了亲眼所见,也为了和我之前写的
commoncache库进行比较,我决定在我自己的机器上,使用同样类型,大小的数据,同样的量级,进行插入数据这个操作的比较。
下面给出我写的测试文件:
针对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';
}
对应的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
而针对commoncache的测试文件是:
/********************************************************************
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的项目代码的test目录中,同样存在一个名为test_unfix_test.c的文件,是我以前写commoncache时测试用的,不过原来的那个文件功能较多,不仅有插入操作,还有查找,替换等操作,这次为了测试,我对这个文件进行了精简,只保留插入数据操作的部分。使用的是commoncache中的hash-rbtree结构。
性能测试结果:
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还是有区别的,前者工作的区域是共享内存,后者是磁盘文件,有这样的表现,确实惊人。
这次比较,起码给了我一些些的自信,我的commoncache不比世界一流的文件数据库性能差的太多。
下一步,我想继续下面的几个工作:
1) 国庆的时候,整理出一份commoncache的设计文档,算是阶段性的一个小结。另外,commoncache在插入数据的时候,有时会报错,我还得查查是为什么。
2) 抽空要开始研究文件数据库的实现了,tokyocabinet就是一个不错的参考。
另外,多说几句,一个产品要成功,仅仅有性能是不够,可维护性,可备份性,优秀的协议设计等等,都是重要的指标。我想,commoncache只做到了性能这一点,我需要在其他几方面继续努力。
哦,忘了给出我的环境参数:
ubuntu9.04,内核2.6.18,内存3G,intel 双核CPU。