之前测试了stackless,感觉不太好.
不过python作为最火的脚本语言,还是吸引力难挡.
python的协程方案,除了stackless,还有greenlet,
相应的事件框架也有gevent ,eventlet等.
先看gevent.
0.x版的gevent是基于libevent的,安装比较简单.还支持windows,先看这个.
1.x版的 gevent改成了libev的, 还需要安转cython,而且没有windows版的...
先来经典的击鼓传花
#!/bin/env python
# -*- coding: utf-8 -*-
#gevent版的击鼓传花(erlang和stackless的经典例子)
#由n个节点组成一个环状网络,在上面传送共m个消息。
#将每个消息(共m个),逐个发送给1号节点。
#第1到n-1号节点在接收到消息后,都转发给下一号节点。
#第n号节点每次收到消息后,不再继续转发。
#当m个消息都从1号逐个到达第n号节点时,认为全部处理结束。
#每次执行时设定n=300,m=10000
import gevent
from gevent.queue import Queue
import sys
if len(sys.argv) < 2:
n=300
m=10000
else:
n=int(sys.argv[1])
m=int(sys.argv[2])
print('start with n=%s,m=%s' % (n,m))
#创建队列
ch=range(1,n)
for i in xrange(1,n):
ch[i-1] = Queue()
#结果队列
#result= Queue()
#定义节点(协程)
def node(i):
while True:
msg = ch[i-1].get()
print('node %s got msg %s' % (i, msg))
if i==n-1:
print ('msg %s reach last node %s' % (msg,i));
else:
ch[i].put_nowait(msg)
if msg>=m-1:
print('final msg %s got,node %s quit' % (msg,i));
break
#初始化消息
for k in xrange(1,m):
print('send %s to node %s' % (k,1))
ch[0].put_nowait(k)
#创建节点(协程)
nodes=range(1,n)
for j in xrange(1,n):
nodes[j-1] = gevent.spawn(node, j)
gevent.joinall(nodes)
#[root@search2 test]# time ./tgering.py 3000 100
#real 0m0.803s
#user 0m0.785s
#sys 0m0.017s
#[root@search2 test]# time ./tgering.py 10000 100
#real 0m2.499s
#user 0m2.469s
#sys 0m0.028s
#[root@search2 test]# time ./tgering.py 100 10000
#real 0m2.201s
#user 0m2.190s
#sys 0m0.009s
#[root@search2 test]# time ./tgering.py 300 10000
#real 0m7.082s
#user 0m7.067s
#sys 0m0.009s
这个性能还是很可观的.
公平起见,在相同环境测试了一下perl的coro性能(基于EV)
两者的差距在可以接受的范围.
#[root@search2 perl]# time ./tring.pl 3000 100
#real 0m1.148s
#user 0m1.128s
#sys 0m0.016s
#[root@search2 perl]# time ./tring.pl 10000 100
#real 0m3.865s
#user 0m3.836s
#sys 0m0.025s
#[root@search2 perl]# time ./tring.pl 300 10000
#real 0m10.564s
#user 0m10.529s
#sys 0m0.024s
#[root@search2 perl]#