将gevent tutorial里的一个小例子略作修改,可以很好地看出协程为何可以比普通的单线程快很多。当然,这是有前提的。在下面的例子中,因为有大量的IO操作,所以才能发挥协程的高效性。在前面的博客中提到"one coroutine per connection"的说法,其实更普通一点,可以说"one coroutine per IO".
先看代码:
import gevent
import random
import time
def task(pid):
"""
Some non-deterministic task
"""
gevent.sleep(random.randint(0,2)*0.1)
print('Task %s done' % pid)
def synchronous():
for i in range(1,10):
task(i)
def asynchronous():
threads = [gevent.spawn(task, i) for i in xrange(10)]
gevent.joinall(threads)
print 'Synchronous:'
start = time.time()
synchronous()
print 'Time Cost: %.1f' % (time.time() - start)
print('Asynchronous:')
start = time.time()
asynchronous()
print 'Time Cost: %.1f' % (time.time() - start)
运行后可知,对于同步的部分,总耗时是所有IO耗时之和;而对于异步的部分,总耗时和单个IO耗时差不多。
这正是因为当一个协程遇到IO阻塞后,即交出CPU控制权,其他不受阻塞的协程接着上。