Python的asyncio模块带来了语言本身的异步功能,不再需要gevent之类的猴子补丁。但速度上,asyncio有点慢。
不过这个库设计之初,就允许了使用自定义的loop代替默认loop。这给更好的性能,带来了可能。
非 Windows
libuv 是一个跨平台的,高性能异步IO库。Node.js被人吹鼓的性能,一半的功劳来自于它。
于是有大佬以它为基础,用Cython写了uvloop,使用的时候只需要两行代码就可以使用性能更好的loop代替原生asyncio默认loop。
import uvloop
uvloop.install()
遗憾的是,由于大佬们很久没用过Windows,并不想自己写Windows的代码。有其他人试图贡献Windows上的代码,但遇到了困难。所以从2016年至今,Windows支持仍然只是uvloop的可行方向,并没有真实可用的代码。
Windows
那么,Windows上真的没有优化途径了吗?答案显然是有。
众所周知,Windows上的IOCP是一种真正的异步IO,它比默认的select性能更佳,libuv在Windows上使用的也是IOCP。
Python的asyncio库自诞生以来,其实就支持IOCP loop,可以调用asyncio.ProactorEventLoop()
去创建一个IOCP loop。
在3.7的版本里,asyncio标准库里增加了asyncio.WindowsProactorEventLoopPolicy
。
所以在Windows上使用IOCP进行优化的代码应该如下:
import sys
import asyncio
if sys.platform == 'win32':
if sys.version_info.major >= 3 and sys.version_info.minor >= 7:
asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())
else:
asyncio.set_event_loop(asyncio.ProactorEventLoop())
这样,ProactorEventLoop
就会代替默认的SelectorEventLoop
,从而在Windows上有更好的性能。
而在Python3.8中,asyncio在Windows上已经开始使用默认IOCP了。Python Document
统一代码
那么结合以上两种代码,可以得出一个复制粘贴即可使用的代码。
if sys.platform == 'win32': # use IOCP in windows
if sys.version_info.major >= 3 and sys.version_info.minor >= 7:
asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())
else:
asyncio.set_event_loop(asyncio.ProactorEventLoop())
else: # try to use uvloop
try:
import uvloop
uvloop.install()
except ImportError:
pass