Tôi đang viết chương trình python được sử dụng để liệt kê tên miền của trang web.Ví dụ, 'a.google.com'.Tại sao thư viện asyncio chậm hơn các luồng cho thao tác I/O-bound này?
Đầu tiên, tôi đã sử dụng các mô-đun threading
để làm điều này:
import string
import time
import socket
import threading
from threading import Thread
from queue import Queue
'''
enumerate a site's domain name like this:
1-9 a-z + .google.com
1.google.com
2.google.com
.
.
1a.google.com
.
.
zz.google.com
'''
start = time.time()
def create_host(char):
'''
if char is '1-9a-z'
create char like'1,2,3,...,zz'
'''
for i in char:
yield i
for i in create_host(char):
if len(i)>1:
return False
for c in char:
yield c + i
char = string.digits + string.ascii_lowercase
site = '.google.com'
def getaddr():
while True:
url = q.get()
try:
res = socket.getaddrinfo(url,80)
print(url + ":" + res[0][4][0])
except:
pass
q.task_done()
NUM=1000 #thread's num
q=Queue()
for i in range(NUM):
t = Thread(target=getaddr)
t.setDaemon(True)
t.start()
for host in create_host(char):
q.put(host+site)
q.join()
end = time.time()
print(end-start)
'''
used time:
9.448670148849487
'''
Sau đó, tôi đọc một cuốn sách mà nói trong một số trường hợp coroutines là nhanh hơn so với chủ đề. Vì vậy, tôi viết lại mã để sử dụng asyncio
:
import asyncio
import string
import time
start = time.time()
def create_host(char):
for i in char:
yield i
for i in create_host(char):
if len(i)>1:
return False
for c in char:
yield c + i
char = string.digits + string.ascii_lowercase
site = '.google.com'
@asyncio.coroutine
def getaddr(loop, url):
try:
res = yield from loop.getaddrinfo(url,80)
print(url + ':' + res[0][4][0])
except:
pass
loop = asyncio.get_event_loop()
coroutines = asyncio.wait([getaddr(loop, i+site) for i in create_host(char)])
loop.run_until_complete(coroutines)
end = time.time()
print(end-start)
'''
time
120.42313003540039
'''
Tại sao là phiên bản asyncio
của getaddrinfo
như vậy là chậm? Tôi có sử dụng sai các coroutines không?
Tôi không thấy sự khác biệt về hiệu suất trên hệ thống của mình. Phiên bản luồng là 20 giây, phiên bản asyncio là 24. Thử xóa câu lệnh in ra khỏi phương thức 'getaddr'. Điều đó có khác biệt lớn về hiệu suất không? In ấn giải phóng GIL, vì vậy nhiều luồng có thể thực hiện đồng thời, trong khi 'asyncio' không thể. Nếu việc in ấn đặc biệt chậm trên hệ thống của bạn, nó có thể giải thích sự khác biệt về tốc độ. – dano