关键字:阻塞队列、非阻塞队列、性能对比、Non-BlockingQueue、BlockingQueue、benchmark、Performance
原文作者:@玄冬Wong
转载请注明出处:http://aigo.iteye.com/blog/
对阻塞和非阻塞队列进行测试:
1,用boost::lockfree::spsc_queue非阻塞队列;(注:spsc_queue是单个生产者单个消费者线程安全的队列,多个生产者多个消费者线程安全的boost::lockfree::queue理论上没有spsc_queue性能好,当然实际上也是这样。。)
2,使用boost::mutex、boost::condition_variable实现的阻塞队列;
先公布结果:
1,如果队列容量足够大,那么非阻塞队列完爆阻塞队列,速度领先至少一个数量级;
2,如果队列容量相对数据总量较小,那么阻塞队列完爆非阻塞队列,速度领先也是一个数量级以上;
现在的服务器动辄32G内存,至于哪种队列更适合服务器,你懂的:)
测试代码:
不同队列容量的测试结果:
读写线程分别执行一千万次的写入和读取操作
阻塞
[test_blocking]
QUEUE_CAPACITY:10
cost:13758ms
count:
[test_blocking]
QUEUE_CAPACITY:1000
cost:1320ms
count:
[test_blocking]
QUEUE_CAPACITY:
cost:1178ms
count:
非阻塞
[test_nonblocking]
QUEUE_CAPACITY:1000
cost:20330ms
count:
[test_nonblocking]
QUEUE_CAPACITY:10000
cost:1827ms
count:
[test_nonblocking]
QUEUE_CAPACITY:
cost:195ms
count:
[test_nonblocking]
QUEUE_CAPACITY:
cost:92ms
count:
[test_nonblocking]
QUEUE_CAPACITY:
cost:90ms
count:
总结:
读写线程分别执行一千万次的写入和读取操作,
阻塞模式下,1000的队列容量就可以将性能发挥到极限:耗时1200毫秒左右;
非阻塞模式下,一百万的队列容量才能将性能发挥到极限:耗时90毫秒以内;
测试环境:
boost 1.60
windows 10 pro x64
VS2015企业版 update2,release x64
CPU:i7二代移动版
补充内容:
1,阻塞和非阻塞的适用环境
这篇文章讲得比较好:如果队列空闲状态占多数,那么阻塞队列性能更好,如果队列有待读取元素的情况占多数,那么非阻塞的无锁队列性能更好。
boost c++ lock-free queue vs shared queue
http://stackoverflow.com/questions//boost-c-lock-free-queue-vs-shared-queue
上面测试情况中,如果队列容量较小,那么读写两个线程大部分时间会是在相互等待;如果容量足够大,那么两个线程可以一路狂奔。
2,java中的阻塞和非阻塞实现
java中的LinkedBlockingQueue,其内部也是通过ReentrantLock和Condition实现阻塞的,上面的结论同样适用于java的相关API。
java中如果要使用无锁队列,可以使用ConcurrentLinkedQueue,其功能相当于boost::lockfree::queue,可支持多个生产者多个消费者的线程。
无锁和非阻塞当以当作同一种概念:阻塞肯定需要锁实现,而非阻塞可以无锁(wait-free)。
3,std::mutex和std::condition_variable的测试结果
将阻塞摸下的相关boost接口换成了std,结果还是一样的,区别不大。
修改代码如下:
输出结果:
[test_blocking]
QUEUE_CAPACITY:1000
cost:1557ms
count:
[test_blocking]
QUEUE_CAPACITY:
cost:1081ms
count:
4,spsc_queue不一定是容量越大性能越好(记)
我通过不同容量和不同循环次数发现:1亿次循环的情况下(相当于生产者填充1亿条消息),spsc_queue的容量超过1000w后(最大容量不能超过8000w),性能将开始下降。
另外,性能取决于生产者和消费者两个线程填充和取出消息的速度,我这里测试时两个线程比较极端,生产者填充消息的速度大概时20w条/1ms,这种情况下,spsc_queue需要的最佳容量为最总1000w;如果生产者和消费者填充和取出消息的速度越慢,则相对容量就越低,我测下来的情况是:1千万次循环,如果生产者和消费者的循环内部再添加一个循环次数为100的逻辑,则两者处理消息的速度均会大幅下降,此时spsc_queue的容量为1w即可发挥最佳性能。
所以结论是:如果想榨干CPU的极限性能,还是得从实际项目中具体的需求上取做测试。个人建议是,将spsc_queue的容量设置为1w,因为一般游戏的上层业务消息的逻辑也挺复杂,估计随便一个逻辑的耗时都能达到1ms,这样一个工作线程1秒内只能处理1000条消息(假设波动范围为1000~5000),那么1w的队列容量是够的(注意是单读单写)。
5,spsc_queue使用相关的优化(记)
之前是每次pop一个元素,现在改成一次pop尽可能多的元素。这样优化以后,1千万次累加,非阻塞队列的耗时能从之前的90毫秒降低到33毫秒。测试发现,获取元素的数组大小设置为512就可以达到最佳性能了。
到此这篇阻塞队列和非阻塞队列哪个好(阻塞队列的作用)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!
版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/bcyy/55130.html