软件开发: 12 2008存档

多线程调试

| | Comments (2) | TrackBacks (0)
      对一个多线程的程序做性能测试时发现不管开多少个线程,CPU的使用率总是停留在160%左右,对于四核的CPU,这显然太低了,肯定是程序里哪部分对线 程锁的使用不当。我第一感觉就把问题定在了BerkeleyDB的 get上,因为打开ENV时我用了DB_THREAD参数,会不会是BDB的线程锁造成的?大概看了看BDB的源码,唔....每个ENV带一个 mutex的HANDLE,这线程锁范围还挺寬,整整锁了一个ENV,也不管里面有多少个DB;而且还是mutex,而不是读写锁,估计即使是get,也 会造成cache的变化,所以只能用互斥锁了。

       于是改程序:一个进程开多个ENV,减少互斥的机会,结果CPU利用率几乎没变;再改:多个进程,每个进程管一个ENV,CPU利用率就上去了!难道 BDB的锁和进程还有关系?干脆,一句句的注释掉代码,一步一步的测性能,最后发现,问题出在我自己写的Log::Debug()函数里,这里面不判断 log的级别就直接加了一个线程锁,结果即使不打印日志,也会锁住线程,造成了运行效率的低下。

      看来调程序还是要先怀疑自己,再怀疑别人。

      04年的时候装了个RedHat 9.0,用了两三个月,在某次编译内核重启失败后换回了windows。
      最近又想起来装个linux玩玩,公司同事很多装ubuntu的,我要是再装一样的就没意思了,所以刻了个fedora 9 的DVD回家装。安装过程和当年装redhat一样,图形化界面,方便。
      装完后我把DVD设成软件包的源,结果麻烦了,装xmms,源里没有,装mplayer,源里没有, 装xfce,源里又没有,下了个xfce来装,又说少了什么vte,下了vte来装,装完了xfce还是说找不到vte....自己装咋就这么费 劲?....唉,最后改回网络做源,才顺利装了xfce,发现xfce界面响应也不是传说中的那么快,似乎和gnome差不多。
       装个mplayer麻烦,装个xmms老崩,用个bt又死慢....linux还是开发和工作用吧,娱乐还是不太适合。
      原先为了在多线程环境下使用bdb,还专门在调用其API前加线程锁。自己加锁除了多出工作量以外,还有一个麻烦:当一个DB的数据很大时,对它的加锁粒度就太大了,会拖慢性能。
后来才发现bdb自己是可以在多线程环境下使用的,只是在DB_ENV初始化时需要加标记:

    DB_ENV *dbenv;
    u_int32_t flags;
    
    flags | = DB_THREAD;
    dbenv->open(dbenv, “/home/data/”, flags, 0);

      在这个DB_ENV下的操作就是线程安全的了,不过还有一点要注意,就是get数据时作为value的DBT需要加DB_DBT_THREAD标记(参考):

    DBT tKey,tValue;
    tValue.flags = DB_DBT_MALLOC;
    ...
    int ret=m_dbp->get(m_dbp,NULL,&tKey,&tValue,0);
    ...
    free(tValue.data);    //由于tValue.data指向的内存是bdb用malloc分配的,所以现在需要用户自己free

       使用bdb自己的多线程支持比外部加锁方便、高效很多。