Próbuję zapoznać się z asyncio, więc postanowiłem napisać klienta bazy danych. Jednak wydajność dokładnie pasuje do kodu synchronicznego. Jestem pewien, że to moje niezrozumienie koncepcji. Czy ktoś mógłby wyjaśnić, co robię?Wydajność asyncio
Proszę patrz przykład kodu poniżej:
class Connection:
def __init__(self, reader, writer, loop):
self.futures = deque()
# ...
self.reader_task = asyncio.async(self.recv_data(), loop=self.loop)
@asyncio.coroutine
def recv_data(self):
while 1:
try:
response = yield from self.reader.readexactly(4)
size, = struct.unpack('I', response)
response = yield from self.reader.readexactly(size)
# ...
future = self.futures.popleft()
if not future.cancelled():
future.set_result(response)
except Exception:
break
def send_data(self, data):
future = asyncio.Future(loop=self.loop)
self.futures.append(future)
self.writer.write(data)
return future
loop = asyncio.get_event_loop()
@asyncio.coroutine
def benchmark():
connection = yield from create_connection(loop=loop, ...)
for i in range(10000):
yield from connection.send_data(...)
s = time.monotonic()
loop.run_until_complete(benchmark())
e = time.monotonic()
print('Requests per second:', int(10000/(e - s)))
Z góry dzięki.
Idealne, dzięki. Z tego, co mogłem zrozumieć, tak samo jak tworzenie zadania dla każdego wywołania "send_data"? – Andrew
@Andrew Mniej więcej, chociaż nadal musisz dodać kod do 'benchmark', aby poczekać na zakończenie każdego' zadania'. Właściwie, uważam, że wywołanie funkcji 'asyncio.wait' spowoduje, że wszystkie obiekty konturu zostaną przekazane do instancji' Task' wewnętrznie. – dano
Tak, obaj jesteście poprawni. 'asyncio.wait' zawija każdy przekazany obiekt typu coroutine lub jest oczekiwany w przyszłości' Task'. Samotny akt owijania ich opcją 'loop.create_task' lub' asyncio.ensure_future' może zaplanować je w pętli, ale nie blokuje wykonania kodu korynkowego, gdy w końcu się kończą.Wciąż będziesz musiał "wydać z' 'zadania' lub przekazać je do czegoś takiego jak 'asyncio.wait'. –