设为首页 加入收藏

TOP

6.5.2 击鼓传花:对比muduo 与libevent2 的事件处理效率
2013-10-07 16:04:04 来源: 作者: 【 】 浏览:77
Tags:6.5.2 击鼓 对比 muduo libevent2 事件 处理 效率

6.5.2 击鼓传花:对比muduo 与libevent2 的事件处理效率

前面我们比较了muduo 和libevent2 的吞吐量, 得到的结论是muduo 比libevent2 快18%. 有人会说,libevent2 并不是为高吞吐量的应用场景而设计的,这样的比较不公平,胜之不武。为了公平起见,这回我们用libevent2 自带的性能测试程序(击鼓传花)来对比muduo 和libevent2 在高并发情况下的IO 事件处理效率。

测试用的软硬件环境与前一小节相同,另外我还在自己的DELL E6400 笔记本电脑上运行了测试,结果也附在后面。

测试的场景是:有1000 个人围成一圈,玩击鼓传花的游戏,一开始第1 个人手里有花,他把花传给右手边的人,那个人再继续把花传给右手边的人,当花转手100次之后游戏停止,记录从开始到结束的时间。

用程序表达是,有1000 个网络连接(socketpair(2) 或pipe(2)),数据在这些连接中顺次传递,一开始往第1 个连接里写1 个字节,然后从这个连接的另一头读出这1 个字节,再写入第2 个连接,然后读出来继续写到第3 个连接,直到一共写了100 次之后程序停止,记录所用的时间。

以上是只有一个活动连接的场景,我们实际测试的是100 个或1000 个活动连接(即100 朵花或1000 朵花,均匀分散在人群手中),而连接总数(即并发数)从100 ~100 000(10 万)。注意每个连接是两个文件描述符,为了运行测试,需要调高每个进程能打开的文件数,比如设为256 000。

libevent2 的测试代码位于test/bench.c,我修复了2.0.6-rc 版里的一个小bug。修正后的代码见已经提交给libevent2 作者,现在下载的最新版本是正确的。

muduo 的测试代码位于examples/pingpong/bench.cc。

测试结果与讨论

第一轮,分别用100 个活动连接和1000 个活动连接,无超时,读写100 次,测试一次游戏的总时间(包含初始化)和事件处理的时间(不包含注册event watcher)随连接数(并发数)变化的情况。具体解释见libev 的性能测试文档19,不同之处在于我们不比较timer event 的性能,只比较IO event 的性能。对每个并发数,程序循环25 次,刨去第一次的热身数据,后24 次算平均值。测试用的脚本20 是libev 的作者Marc Lehmann 写的,我略做改用,用于测试muduo 和libevent2。

第一轮的结果(见图6-6),请先只看“+”线(实线)和“”线(粗虚线)。“”线是libevent2 用的时间,“+”线是muduo 用的时间。数字越小越好。注意这个图的横坐标是对数的,每一个数量级的取值点为1,2,3,4,5,6,7.5,10。

 

从两条线的对比可以看出:

1. libevent2 在初始化event watcher 方面比muduo 快20% (左边的两个图)。

2. 在事件处理方面(右边的两个图)

a. 在100 个活动连接的情况下,

当总连接数(并发数)小于1000 或大于30 000 时,二者性能差不多;

当总连接数大于1000 或小于30 000 时,libevent2 明显领先。

b. 在1000 个活动连接的情况下,

当并发数小于10 000 时,libevent2 和muduo 得分接近;

当并发数大于10 000 时,muduo 明显占优。

这里有两个问题值得探讨:

1. 为什么muduo 花在初始化上的时间比较多?

2. 为什么在一些情况下它比libevent2 慢很多?

我仔细分析了其中的原因,并参考了libev 的作者Marc Lehmann 的观点21,结论是:在第一轮初始化时,libevent2 和muduo 都是用epoll_ctl(fd, EPOLL_CTL_ADD, ...) 来添加文件描述符的event watcher。不同之处在于,在后面24 轮中,muduo 使用了epoll_ctl(fd, EPOLL_CTL_MOD, ...) 来更新已有的event watcher;然而libevent2 继续调用epoll_ctl(fd, EPOLL_CTL_ADD, ...) 来重复添加fd,并忽略返回的错误码EEXIST (File exists)。在这种重复添加的情况下,EPOLL_CTL_ADD将会快速地返回错误,而EPOLL_CTL_MOD 会做更多的工作,花的时间也更长。于是libevent2 捡了个便宜。

为了验证这个结论,我改动了muduo,让它每次都用EPOLL_CTL_ADD 方式初始化和更新event watcher,并忽略返回的错误。

第二轮测试结果见图6-6 的细虚线,可见改动之后的muduo 的初始化性能比libevent2 更好,事件处理的耗时也有所降低(我推测是kernel 内部的原因)。

这个改动只是为了验证想法,我并没有把它放到muduo 最终的代码中去,这或许可以留作日后优化的余地。(具体的改动是muduo/net/poller/EPollPoller.cc 第138 行和173 行,读者可自行验证。)

同样的测试在双核笔记本电脑上运行了一次,结果如图6-7 所示。(我的笔记本电脑的CPU 主频是2.4 GHz,高于台式机的1.86 GHz,所以用时较少。)

 
结论:在事件处理效率方面,muduo 与libevent2 总体比较接近,各擅胜场。在并发量特别大的情况下(大于10 000),muduo 略微占优。

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇6.5.1 muduo 与Boost.Asio、libev.. 下一篇6.5.3 muduo 与Nginx 的吞吐量对..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·用 C 语言或者限制使 (2025-12-25 08:50:05)
·C++构造shared_ptr为 (2025-12-25 08:50:01)
·既然引用计数在做 GC (2025-12-25 08:49:59)
·Java 编程和 c 语言 (2025-12-25 08:19:48)
·. net内存管理宝典这 (2025-12-25 08:19:46)