Python几种并发实现方案性能比较.docx

合集下载
相关主题
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

偶然看到Erlang vs. Stackless python: a first benchmark,对Erlang和Stackless Python的并发处理性能进行了实验比较,基本结论认为二者有比较相近的性能。我看完产生的问题是,Stackless Python与Python的其他并发实现机制性能又会有多大区别呢,比如线程和进程。因此我采用与这篇文章相同的办法来对Stackless Python、普通Python的thread模块、普通Python的threading模块、普通Python的processing模块这四种并发实现方案进行了性能实验,并将实验

实验方案与Erlang vs. Stackless python: a first benchmark是相同的,用每种方案分别给出如下问题的实现,记录完成整个处理过程的总时间来作为评判性能的依据:

1.由n个节点组成一个环状网络,在上面传送共m个消息。

2.将每个消息(共m个),逐个发送给1号节点。

3.第1到n-1号节点在接收到消息后,都转发给下一号节点。

4.第n号节点每次收到消息后,不再继续转发。

5.当m个消息都从1号逐个到达第n号节点时,认为全部处理结束。

(Edit Section ↓)

2.1 硬件平台

Macbook Pro 3,1上的Vmware Fusion 1.0虚拟机中,注意这里给虚拟机只启用了cpu的单个核心:

•原始Cpu:Core 2 Duo,2.4 GHz,2核心,4 MB L2 缓存,总线速度800 MHz

•分配给虚拟机的内存:796M

(单个CPU,还能比较并发吗?)

(Edit Section ↓)

2.2 软件平台

Vmware Fusion 1.0下的Debian etch:

•原始Python:Debian发行版自带Python 2.4.4

•Python 2.4.4 Stackless 3.1b3 060516

•processing-0.52-py2.4-linux-i686.egg

•原始Python下的greenlet实现:py lib 0.9.2

各方案的实现代码见后文。实验时使用time指令记录每次运行的总时间,选用的都是不做任何输出的no_io实现(Python的print指令还是挺耗资源的,如果不注释掉十有八九得影响测试结果),每次执行时设定n=300,m=10000(Erlang vs. Stackless python: a first benchmark文章中认为n可以设置为300,m则可以取10000到90000之间的数值分别进行测试)。

(Edit Section ↓)

3.1 Stackless Python的实验结果

real 0m1.651s

user 0m1.628s

sys 0m0.020s

即使将m扩大到30000,实验结果仍然很突出:

real 0m4.749s

user 0m4.716s

sys 0m0.028s

(Edit Section ↓)

3.2 使用thread模块的实验结果

real 1m13.009s

user 0m2.476s

sys 0m59.028s

(Edit Section ↓)

3.3 使用threading模块配合Queue模块的实验结果不太稳定,有时候这样:

real 1m9.222s

user 0m34.418s

sys 0m34.622s

也有时这样:

real 2m14.016s

user 0m6.644s

sys 2m7.260s

(Edit Section ↓)

3.4 使用processing模块配合Queue模块的实验结果real 3m43.539s

user 0m15.345s

sys 3m27.953s

(Edit Section ↓)

4.1 Stackless Python

毫无疑问,Stackless Python几乎有匪夷所思的并发性能,比其他方案快上几十倍,而且借助Stackless Python提供的channel机制,实现也相当简单。也许这个结果向我们部分揭示了沈仙人基于Stackless Python实现的Eurasia3能够提供相当于c语言效果的恐怖并发性能的原因。

(Edit Section ↓)

4.2 Python线程

从道理上来讲,thread模块似乎应该和threading提供基本相同的性能,毕竟threading只是对thread的一种封装嘛,后台机制应该是一致的。或许threading 由于本身类实例维护方面的开销,应该会比直接用thread慢一点。从实验结果来看,二者性能也确实差不多。只是不大明白为何threading方案的测试结果不是很稳定,即使对其他方案的测试运行多次,误差也不会像threading这么飘。从代码实现体验来说,用threading配合Queue比直接用thread实在是轻松太多了,并且出错的机会也要少很多。

(Edit Section ↓)

4.3 Python进程

processing模块给出的进程方案大致比thread线程要慢一倍,并且这是在我特意调整虚拟机给它预备了足够空闲内存、避免使用交换分区的情况下取得的(特意分给虚拟机700多M内存就是为了这个)。而其他方案仅仅占用数M内存,完全无需特意调大可用内存总量。当然,如果给虚拟机多启用几个核心的话,processing也许会占上点便宜,毕竟目前thread模块是不能有效利用多cpu资源的(经实验,Stackless Python在开启双核的情况下表现的性能和单核是一样的,说明也是不能有效利用多cpu)。因此一种比较合理的做法是根据cpu的数量,启用少量几个进程,而在进程内部再开启线程进行实际业务处理,这也是目前Python社区推荐的有效利用多cpu资源的办法。好在processing配合其自身提供的Queue模块,编程体验还是比较轻松的。

(Edit Section ↓)

4.4 greenlet超轻量级方案

基于greenlet的实现则性能仅次于Stackless Python,大致比Stackless Python 慢一倍,比其他方案快接近一个数量级。其实greenlet不是一种真正的并发机制,而是在同一线程内,在不同函数的执行代码块之间切换,实施“你运行一会、我运行一会”,并且在进行切换时必须指定何时切换以及切换到哪。greenlet的接口是比较简单易用的,但是使用greenlet时的思考方式与其他并发方案存在一定区别。线程/进程模型在大逻辑上通常从并发角度开始考虑,把能够并行处理的并且值得并行处理的任务分离出来,在不同的线程/进程下运行,然后考虑分离过程可能造成哪些互斥、冲突问题,将互斥的资源加锁保护来保证并发处理

相关文档
最新文档