背景

   该篇博文是在看了一些文献,说是使用条件变量+互斥量会比使用信号量效率高,而以前看书的时候,觉得其它们是信号量的特例,直觉觉得只是简化了使用。虽然很多场景也没有必要使用信号量的计数,但是正如《win32 多线程程序设计》提的,有些场景必须使用(在没有条件变量的情况下)。因此测一下,条件变量与信号量的并发性能对比。

多线程的循环队列见另外本人的另外一篇博文(http://blog.chinaunix.net/uid-28993794-id-5770897.html

由于另外两个版本的循环队列,以及完整的测试程序,代码显得有点多就不贴了,描述一下测试场景!(从该篇文章可以看出队列的一个并发问题,但是不影响测试)

概述

本文一共做了两次测试——结果看第二次测试就好了。第一次测试时是遇到了一点问题,以及有测试程序有BUG。第二次测试解决了此BUG,以及使用更大的数据来测试。

基本数据模型

    每个生产者和消费者都为一个线程,各自向队列中放、取一个消息(多个消息只能一个一个放)。生产者不能向满队列中放消息,消费者不能消费空消息。如果条件不满足,阻塞直到满足条件。

一个消息,简单定义为:


点击(此处)折叠或打开

  1. class Student
  2. {

  3. public:

  4.     Student() {}

  5.     Student(const char* strName, int iAge, char chSex = 1):name(strName), age(iAge), sex(chSex){}

  6.     stl_char32 name;

  7.     int age;

  8.     char sex;

  9. }



测试环境:

环境

VMWare

系统

Centos7_x64

CPU

1

内存

1GB


测试结果

测试的思路为:每个生产者生产1万消息,调整生产者、消费者数量,缓冲区大小(循环队列大小),使并发数量达到最大。

但是测出来的数据有跳变的现象,经过分析,是总的测试时间太短导致误差。(数据没有实际参考意义就不贴了)。第二次将消息量改为了1亿,数据就比较相对比较稳定(条件变量还是有很大偏差,如果改为10亿偏差又会小很多,不过对于信号量来说执行时间过长。考虑到误差与对比的结果来说已经具有说服力,故还是采用1亿消息量进行测试)。


条件变量

生产者、消费者两个,缓冲区1万,消息量1亿。原始数据3组(时间单位为us,速率单位:/ms):

序号

消息数量

生产时间

生产速率

消费时间

消费者速率

1

100000000

33586668

2977.372

36325765

2752.867008

 

100000000

34083701

2933.954

36323483

2753.039955

2

100000000

33605133

2975.736

36979767

2704.181451

 

100000000

35280315

2834.442

36589686

2733.010609

3

100000000

35826637

2791.219

37227484

2686.187442

 

100000000

34924632

2863.309

37674271

2654.331387


从表中计算的平均值等,与程序统计的一致,此处就不整理表格了。

从该表可以看出,至少数字没有太大的跳变了,因此用该方法统计几组数据:

生产速率

消费者速率

差值

高多少

偏差

2903.37

2718.52

184.85

6.80%

1.34%

2955.5

2752.95

202.55

7.36%

9.66%

2826.8

2670.16

156.64

5.87%

-12.57%

2993.23

2783.77

209.46

7.52%

12.14%

2924.19

2758.67

165.52

6.00%

-10.58%

2950.77

2721.45

229.32

8.43%

25.59%

2874.57

2757.5

117.07

4.25%

-36.72%

2918.347

2737.57429

180.7728571

6.71%

 

 

 

 直接算平均值

6.60%

 


该表统计了生产速率和消费速率的关系——考虑了测试中的误差。

信号量

测试案例都一样:

生产速率

消费者速率

差值

高多少

844.108

844.289

-0.181

-0.02%

843.285

844.689

-1.404

-0.17%

851.864

851.705

0.159

0.02%

841.78

838.346

3.434

0.41%

836.372

835.402

0.97

0.12%

从上面可以看出信号量的误差要小很多。 

条件变量10亿:

信号量的误差较小,因此增加测试10亿部分,生产者和消费者速率分别是:2856.482675.15。比开始测出的数据还要小,因此将缓冲区增大到100万。结果分别是:2827.632679.1 

从这里可以看出,似乎增大测试量,生产者和消费者的速率是在靠近的。但是无法证明。

 

说明:

    测试时,CPU会持续100%,内存使用1万缓冲区0.1%,使用100万缓冲区4%。时间可以从表中看出。

总结

  1. 信号量速率比条件变量小很多(1/3)(信号量根据操作系统中标准的PV操作来实现的。)

  2. 同样的测试程序,且生产者和消费者都是做一次memcpy,信号量的生产者和消费者速率会更匹配一点。

10-18 07:02