2011-12-27

今天把Berkeley DB加进去,加到昨天的测试代码中。然后把client改成多线程的,其实就是为了方便启动测试。

首先,当服务器端是单线程的时候,一切都工作的很好,QPS也不低。

然后,我把服务器改成多线程,共享一个db handle。然后立马就死锁了。速度非常快。

嗯,用锁的时候必须把死锁检测打开。

dbenv->set_lk_detect(DB_LOCK_DEFAULT);

你猜怎么着?

第一次测试,很OK,插入20万条数据(key是用java.util.Random.nextLong生的),花了23秒。

第二次,卡死了。我以为又是死锁,但是用pstack打开一看,不是。好多线程在等锁,还有好多线程停留在pwrite状态下:

#0 0x00000030d56c4aa8 in pwrite64 () from /lib64/libc.so.6
#1 0x00000000004b1852 in __os_io ()
#2 0x000000000057872c in __memp_pgwrite ()
#3 0x0000000000578974 in __memp_bhwrite ()
#4 0x00000000005772cc in __memp_alloc ()
#5 0x00000000004a15f7 in __memp_fget ()
#6 0x00000000004ef276 in __ham_get_cpage ()
#7 0x00000000004e7011 in __ham_lookup ()
#8 0x00000000004e7814 in __hamc_put ()
#9 0x000000000045ffe1 in __dbc_iput ()
#10 0x00000000004613e0 in __dbc_put ()
#11 0x000000000045ccbe in __db_put ()
#12 0x000000000046b112 in __db_put_pp ()
#13 0x0000000000445ba6 in Db::put(DbTxn*, Dbt*, Dbt*, unsigned int) ()
#14 0x00000000004426e0 in MyService::put(google::protobuf::RpcController*, AdPlayData const*, VoidResponse*, google::protobuf::Closure*) ()

用iostat看,每秒的写入量大概是1.0MB-1.2MB左右,非常低,低的可怕,而硬盘的tps是200-350之间。用top看,系统负载一直是22上下。可能是因为我开了20个线程。最奇特的在于,用vmstat看,running队列始终为0 。CPU的us和sy 也是0。id=85%,wa=15%左右。但是系统负载一直是22。我猜是因为vmstat的输出是每秒一次,所以与系统的实际情况相差太远。

这还没完。就算每秒写1MB,也有写完的时候吧?这个,最神奇的地方在于,我不知道它在写什么文件!我用lsof看它所有打开的文件,然后这些文件,并未每秒改变大小。实际上,写入速度每分钟都不到10MB/s。

这个事实告诉我,当Berkeley DB的cache效果很差的时候,它到底能有多差!!

下班,吃饭去。明天再想到底为什么。反正,解决办法很简单,不要用它的cache,自己做cache,或者,至少把数据库部分改成单线程的。

此博客中的热门博文

少写代码,多读别人写的代码

在windows下使用llvm+clang

tensorflow distributed runtime初窥