对Berkeley DB的性能进行的部分测试
零 环境说明:
所有的数据插入的都是Key=int,Value=int,在循环中递增的.
本机NTFS的默认簇大小为4K.
本机配置仅仅影响绝对值.相对值是可比较的:
OS=WinXP SP2;RAM= 1G ;CPU=AMD Athlon 64 X2 Dual 5000+;Disk= 160G
测试的实际数据量为:300*10000*2*sizeof(int)/1024/1024~=22.89MByte
下面所有的测试结果的单位都是秒.
编译器:C++ builder 6.0(使用bcb编译BDB源码,形成LIB库后,直接链接到测试程序中.没有测试DLL的形式.)
BDB版本: 4.6.21 .NC
一 测试页尺寸对读写性能的影响:
记录数量 =300万 缓存尺寸= 0M
读写\页尺寸 |
1K |
2K |
4K |
8K |
16K |
32K |
B+写 |
94.94 |
84.83 |
82.73 |
97.16 |
142.67 |
232.11 |
HASH写 |
346.16 |
320.41 |
288.36 |
295.19 |
599.66 |
867.03 |
B+读 |
4.22 |
4.06 |
3.86 |
3.91 |
3.80 |
3.78 |
HASH读 |
8.25 |
7.94 |
5.42 |
5.41 |
4.99 |
4.88 |
结论:页尺寸与文件系统的簇大小相同时,写入性能最佳,读取性能中等.
在 0M 缓存的时候,B+的性能要比HASH好得多.
二 测试cache缓存大小对读写性能的影响:
记录数量=300万 页尺寸=4K 真实数据量=22.89MByte 数据库文件大小= 80M
读写\缓存 |
0M |
10M |
20M |
40M |
80M |
160M |
320M |
B+写 |
85.06 |
88.66 |
133.31 |
164.81 |
15.31 |
15.34 |
15.27 |
HASH写 |
292.91 |
224.47 |
180.76 |
95.28 |
20.11 |
20.06 |
20.05 |
B+读 |
3.98 |
4.17 |
4.86 |
9.56 |
3.83 |
3.81 |
3.80 |
HASH读 |
5.53 |
5.83 |
5.83 |
8.16 |
5.20 |
5.08 |
5.16 |
记录数量=600万 页尺寸=4K 真实数据量=45.78MByte 数据库文件大小= 160M
读写\缓存 |
0M |
40M |
80M |
160M |
320M |
B+写 |
259.39 |
1198.27 |
1017.94 |
34.59 |
34.30 |
HASH写 |
1889.32 |
1279.95 |
563.12 |
40.67 |
40.89 |
B+读 |
7.89 |
14.02 |
22.84 |
7.97 |
8.03 |
HASH读 |
11.17 |
16.81 |
11.66 |
10.39 |
10.88 |
结论:
对于缓存大于数据库文件尺寸的时候,没有太多可说的,操作都在内存中,速度非常快.
对于大数据量的读取,两组对比都比较清晰的说明了一点:缓存的大小对读取记录的性能影响不是很大.
对于大数据量的写入,缓存对性能的影响就非常可观了,基本可以肯定的是,HASH库缓存越大写入速度越快. 而奇怪的是,B+库在缓存不足的时候,性能反而比0缓存时还要差很多!!
总的来说,在我的这些测试中,B+与HASH数据库的性能差异很大.
对于缓存大于物理内存的情况未做测试,估计对性能不会有好的影响,毕竟在这种情况下,效率的瓶颈都是在磁盘的IO上.
测试的核心代码如下:
Cpp代码
- #include <db_cxx.h>
- #define DATABASE "access.db"
- //tcount=记录数为多少万次,DbType=数据库类型,psize=页尺寸K,csize=缓存尺寸M
- void run(int tcount,DBTYPE DbType,size_t psize,size_t csize)
- {
- remove(DATABASE);
- Db db(0, 0);
- db.set_errpfx("AccessExample");
- db.set_pagesize(1024*psize);
- db.set_cachesize(0, 1024*1024*csize, 0);
- db.open(NULL, DATABASE, NULL, DbType, DB_CREATE|DB_THREAD, 0664);
- int testcount=10000*tcount;
- size_t tick1=GetTickCount();
- for (int i=0;i<testcount;i++)
- {
- Dbt key(&i,sizeof(int));
- Dbt data(&i,sizeof(int));
- db.put(0, &key, &data, DB_NOOVERWRITE);
- }
- printf("插入结束 %d 万记录,全部用时:% .2f 秒\r\n",tcount,(GetTickCount()-tick1)/(float)1000);
- tick1=GetTickCount();
- try
- {
- Dbc *dbcp;
- db.cursor(NULL, &dbcp, 0);
- Dbt key;
- Dbt data;
- while (dbcp->get(&key, &data, DB_NEXT) == 0)
- {
- key.get_data();
- data.get_data();
- }
- dbcp->close();
- printf("遍历结束 %d 万记录,全部用时:% .2f 秒\r\n",tcount,(GetTickCount()-tick1)/(float)1000);
- db.sync(0);
- }
- catch (DbException &dbe) {}
- db.close(0);
- }
#include <db_cxx.h>
#define DATABASE "access.db"
//tcount=记录数为多少万次,DbType=数据库类型,psize=页尺寸K,csize=缓存尺寸M
void run(int tcount,DBTYPE DbType,size_t psize,size_t csize)
{
remove(DATABASE);
Db db(0, 0);
db.set_errpfx("AccessExample");
db.set_pagesize(1024*psize);
db.set_cachesize(0, 1024*1024*csize, 0);
db.open(NULL, DATABASE, NULL, DbType, DB_CREATE|DB_THREAD, 0664);
int testcount=10000*tcount;
size_t tick1=GetTickCount();
for (int i=0;i<testcount;i++)
{
Dbt key(&i,sizeof(int));
Dbt data(&i,sizeof(int));
db.put(0, &key, &data, DB_NOOVERWRITE);
}
printf("插入结束 %d 万记录,全部用时:%.2f秒\r\n",tcount,(GetTickCount()-tick1)/(float)1000);
tick1=GetTickCount();
try
{
Dbc *dbcp;
db.cursor(NULL, &dbcp, 0);
Dbt key;
Dbt data;
while (dbcp->get(&key, &data, DB_NEXT) == 0)
{
key.get_data();
data.get_data();
}
dbcp->close();
printf("遍历结束 %d 万记录,全部用时:%.2f秒\r\n",tcount,(GetTickCount()-tick1)/(float)1000);
db.sync(0);
}
catch (DbException &dbe) {}
db.close(0);
}
分享到:
关于一些中文分词器
- 17:01
- 评论 / 浏览 (4 / 3987)
- 相关推荐
评论
4 楼 h_rain 2009-02-22
结论:页尺寸与文件系统的簇大小相同时,写入性能最佳,读取性能中等.
缓存用尽后,性能的瓶颈就在于磁盘IO.
BDB内部对IO进行了优化,每次操作都是对"页尺寸"字节进行处理,就是说,读写10字节或100字节的时候,其实都是在"页尺寸"这么大的内存上进行读写,之后一次性将一个页写入磁盘.你给定的页尺寸是8k,但ntfs默认的"簇"大小是4k,所以这样的操作要跨簇进行,效率就低了.
建议根据文件系统的"簇"大小设置BDB的"页尺寸".
这样的话,耗时基本是定长的了.
3 楼 peter_wu 2009-02-20
观察任务管理器,发现速度快的时候,cache还没有用完,没有IO操作。当内存不再增长,cache用完的时候,IO开始大量读取和写入,速度开始下降。原来如此啊。
2 楼 peter_wu 2009-02-20
插入一个周期,10w 用时 0.00 秒
插入一个周期,10w 用时 0.92 秒
插入一个周期,10w 用时 1.09 秒
插入一个周期,10w 用时 1.11 秒
插入一个周期,10w 用时 1.14 秒
插入一个周期,10w 用时 1.16 秒
插入一个周期,10w 用时 1.19 秒
插入一个周期,10w 用时 1.14 秒
插入一个周期,10w 用时 1.19 秒
插入一个周期,10w 用时 1.20 秒
插入一个周期,10w 用时 1.20 秒
插入一个周期,10w 用时 1.28 秒
插入一个周期,10w 用时 1.22 秒
插入一个周期,10w 用时 1.17 秒
插入一个周期,10w 用时 1.20 秒
插入一个周期,10w 用时 1.19 秒
插入一个周期,10w 用时 1.20 秒
插入一个周期,10w 用时 1.26 秒
插入一个周期,10w 用时 1.24 秒
插入一个周期,10w 用时 1.16 秒
插入一个周期,10w 用时 1.17 秒
插入一个周期,10w 用时 1.38 秒
插入一个周期,10w 用时 1.19 秒
插入一个周期,10w 用时 1.20 秒
插入一个周期,10w 用时 1.16 秒
插入一个周期,10w 用时 1.19 秒
插入一个周期,10w 用时 1.17 秒
插入一个周期,10w 用时 1.22 秒
插入一个周期,10w 用时 1.17 秒
插入一个周期,10w 用时 1.20 秒
插入一个周期,10w 用时 1.22 秒
插入一个周期,10w 用时 1.28 秒
插入一个周期,10w 用时 1.19 秒
插入一个周期,10w 用时 1.33 秒
插入一个周期,10w 用时 1.19 秒
插入一个周期,10w 用时 1.23 秒
插入一个周期,10w 用时 1.22 秒
插入一个周期,10w 用时 1.20 秒
插入一个周期,10w 用时 1.22 秒
插入一个周期,10w 用时 1.23 秒
插入一个周期,10w 用时 1.42 秒
插入一个周期,10w 用时 1.22 秒
插入一个周期,10w 用时 1.19 秒
插入一个周期,10w 用时 1.27 秒
插入一个周期,10w 用时 5.84 秒
插入一个周期,10w 用时 9.52 秒
插入一个周期,10w 用时 14.03 秒
插入一个周期,10w 用时 15.39 秒
插入一个周期,10w 用时 16.44 秒
插入一个周期,10w 用时 20.39 秒
插入结束 500 万记录,全部用时:156.05秒
遍历结束 500 万记录,全部用时:14.11秒
请按任意键继续. . .
1 楼 peter_wu 2009-02-20
我改了下代码,发现一个问题,随着时间推移,插入效率下降严重,请问是为什么。
Java代码
- #include <db_cxx.h>
- #include <Windows.h>
- #define DATABASE "access.db"
- void run(int tcount,DBTYPE DbType,size_t psize,size_t csize) ;
- void main(int argc,char * argv[])
- {
- run(500,DB_BTREE,8,100);
- }
- //tcount=记录数为多少万次,DbType=数据库类型,psize=页尺寸K,csize=缓存尺寸M
- void run(int tcount,DBTYPE DbType,size_t psize,size_t csize)
- {
- remove(DATABASE);
- Db db(0, 0);
- db.set_errpfx("AccessExample");
- db.set_pagesize(1024*psize);
- db.set_cachesize(0, 1024*1024*csize, 0);
- db.open(NULL, DATABASE, NULL, DbType, DB_CREATE|DB_THREAD, 0664);
- int testcount=10000*tcount;
- size_t tick1=GetTickCount();
- DWORD inlinetick=tick1;
- for (int i=0;i<testcount;i++)
- {
- Dbt key(&i,sizeof(int));
- Dbt data(&i,sizeof(int));
- db.put(0, &key, &data, DB_NOOVERWRITE);
- if (i%100000==0)
- {
- printf("插入一个周期,10w 用时 % .2f 秒\n",(GetTickCount()-inlinetick)/(float)1000);
- inlinetick=GetTickCount();
- }
- }
- printf("插入结束 %d 万记录,全部用时:% .2f 秒\r\n",tcount,(GetTickCount()-tick1)/(float)1000);
- tick1=GetTickCount();
- try
- {
- Dbc *dbcp;
- db.cursor(NULL, &dbcp, 0);
- Dbt key;
- Dbt data;
- while (dbcp->get(&key, &data, DB_NEXT) == 0)
- {
- key.get_data();
- data.get_data();
- }
- dbcp->close();
- printf("遍历结束 %d 万记录,全部用时:% .2f 秒\r\n",tcount,(GetTickCount()-tick1)/(float)1000);
- db.sync(0);
- }
- catch (DbException &dbe) {}
- db.close(0);
- }