Sto scrivendo un programma python utilizzato per enumerare il nome di dominio di un sito.Ad esempio, 'a.google.com'.Perché la libreria asyncio è più lenta dei thread per questa operazione legata all'I/O?
In primo luogo, ho usato il modulo threading
per fare questo:
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
'''
Più tardi, ho letto un libro che ha detto, in alcuni casi coroutine sono più veloce di discussioni. Così, ho riscritto il codice per utilizzare 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
'''
Perché è la versione asyncio
di getaddrinfo
è così lento? Sto abusando delle coroutine in qualche modo?
Non vedo quasi nessuna differenza di prestazioni sul mio sistema. La versione filettata era di 20 secondi, la versione di asyncio era 24. Prova a rimuovere la dichiarazione di stampa dal metodo 'getaddr'. Ciò rende le prestazioni molto diverse? La stampa rilascia GIL, quindi molti thread possono farlo contemporaneamente, mentre 'asyncio' non può. Se la stampa è particolarmente lenta sul sistema, potrebbe tenere conto della differenza di velocità. – dano