通过读取网页的响应码来试下异步编程。
首先使用最传统的方式来试一下,每次测试100下。
主要代码如下(3.5.2)
s = socket(AF_INET, SOCK_STREAM)
try:
s.connect(('www.yunxcloud.cn', 80))
except BlockingIOError:
pass
request = 'GET %s HTTP/1.0\r\n\r\n' % path
s.send(request.encode())
buf = []
while True:
chunk = s.recv(1000)
if not chunk:
break
buf.append(chunk)
s.close()
print((b''.join(buf)).decode().split('\n')[0])
time cost18.625152349472046
发现socket连接是阻塞的 将其设置为非阻塞,注册到事件循环中
这时就有了点异步的意思了
主要添加的代码如下:
s.setblocking(False)
selector.register(s.fileno(), EVENT_WRITE, lambda : connected(s, path))
while n_jobs:
events = selector.select()
for key, mask in events:
callback = key.data # connected callback
callback()
time cost9.98605465888977
上一个不完善的版本中 时间已经提升到了之前的一半。
在分开来分析 连接到服务器会阻塞 将数据发送过去会阻塞 数据下载下来会阻塞
将这几个步骤拆开。
selector.register(s.fileno(), EVENT_WRITE, lambda : connected(s, path))
def connected(s, path):
selector.unregister(s.fileno())
selector.register(s.fileno(), EVENT_READ, lambda : readable(s, buf))
chunk = s.recv(1000)
if chunk:
buf.append(chunk)
else:
selector.unregister(s.fileno())
现在时间更是一个恐怖的提升time cost0.3132033348083496
再往后的提升就是抽象出专门的类来进行处理,但是时间方面的提升不会太大了
参考视频
参考文档
参考代码 版本1 同步阻塞
参考代码 版本2 非阻塞
参考代码 版本3 非阻塞 将会产生等待的地方拿出来利用