通過讀取網(wǎng)頁的響應(yīng)碼來試下異步編程。
首先使用最傳統(tǒng)的方式來試一下,每次測試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
發(fā)現(xiàn)socket連接是阻塞的 將其設(shè)置為非阻塞,注冊(cè)到事件循環(huán)中
這時(shí)就有了點(diǎn)異步的意思了
主要添加的代碼如下:
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
上一個(gè)不完善的版本中 時(shí)間已經(jīng)提升到了之前的一半。
在分開來分析 連接到服務(wù)器會(huì)阻塞 將數(shù)據(jù)發(fā)送過去會(huì)阻塞 數(shù)據(jù)下載下來會(huì)阻塞
將這幾個(gè)步驟拆開。
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())
現(xiàn)在時(shí)間更是一個(gè)恐怖的提升time cost0.3132033348083496
再往后的提升就是抽象出專門的類來進(jìn)行處理,但是時(shí)間方面的提升不會(huì)太大了
參考視頻
參考文檔
參考代碼 版本1 同步阻塞
參考代碼 版本2 非阻塞
參考代碼 版本3 非阻塞 將會(huì)產(chǎn)生等待的地方拿出來利用