Задать вопрос
YardalGedal
@YardalGedal
yeah boy

Чем обусловлена такая разница в асинхронной обработке запросов?

Есть endpoint на aiohttp с uvloop'ом, тестирую siege'ом, есть два тестовых случая: в одном используется asyncio.create_task(func()), что создаёт асинхронную задачу и обрабатывает её, но нигде не используется await этой задачи, так как её результат мне не нужен и она просто должна отработать, а в другом используется await func().
Результаты тестирований:
Transactions:		        4549 hits
Availability:		      100.00 %
Elapsed time:		       29.72 secs
Data transferred:	        0.01 MB
Response time:		        1.02 secs
Transaction rate:	      153.06 trans/sec
Throughput:		        0.00 MB/sec
Concurrency:		      156.78
Successful transactions:        4549
Failed transactions:	           0
Longest transaction:	        3.23
Shortest transaction:	        0.11

Transactions:		        4638 hits
Availability:		       99.42 %
Elapsed time:		       29.34 secs
Data transferred:	        0.11 MB
Response time:		        0.81 secs
Transaction rate:	      158.08 trans/sec
Throughput:		        0.00 MB/sec
Concurrency:		      128.02
Successful transactions:        4638
Failed transactions:	          27
Longest transaction:	        7.42
Shortest transaction:	        0.14


Как можно заметить, время самого длительного и самого медленного запросов во втором случае больше (самый длительный запрос - в два раза), однако конкурентность и среднее время ответа (20% - достаточно существенно) меньше, но при этом количество обработанных транзакций за время тестирования больше как и среднее количество обрабатываемых транзакций в секунду.

Почему так получается? Стоит ли использовать asyncio.create_task везде, где мне не нужен результат задачи?
  • Вопрос задан
  • 441 просмотр
Подписаться 3 Простой Комментировать
Решения вопроса 1
@lega
1) Отличие этих 2-х результатов это "Data transferred:", второй вариант передал в 10 раз больше данных, значит больше работы - меньше rps - т.е. тесты не эквивалентны

2) если вам не надо ждать результат то не используйте await, тогда завершить запрос можно будет быстрее

в целом create_task не даст вам большую производительность, а асинхронный вызов не может занимать ни 3 ни 7 сек, скорее у вас код блокирующий или тормозной, и ни asyncio ни aiohttp тут не причем.

PS: asyncio + uvloop могут выдавать до 100к rps на среднем ноутбуке в один поток, поэтому не это причина ваших 150rps

--- тест asyncio + uvloop + httptools на среднем ноутбуке
Результат: 123krps, и max latency 6.74ms

Запуск wrk:
$ docker run --rm -it --network=host williamyeh/wrk -c 200 -d 10 http://localhost:8888/

Результат:
Running 10s test @ http://localhost:8888/
  2 threads and 200 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     1.59ms  404.50us   6.74ms   58.61%
    Req/Sec    62.18k     7.51k   74.02k    68.00%
  1237743 requests in 10.06s, 47.22MB read
Requests/sec: 123044.52
Transfer/sec:      4.69MB

import asyncio
import uvloop
from httptools import HttpRequestParser

class RpcProtocol(asyncio.Protocol):
    def connection_made(self, transport):
        self.transport = transport
        self.parser = HttpRequestParser(self)

    def connection_lost(self, exc):
        self.transport = None

    def data_received(self, data):
        self.parser.feed_data(data)

    def on_message_complete(self):
        #if self.url == b'/hello':
        response = b'HTTP/1.1 200 OK\nContent-Length: 5\n\nHello'
        self.transport.write(response)

        if not self.parser.should_keep_alive():
            self.transport.close()
            self.transport = None

if __name__ == '__main__':
    loop = uvloop.new_event_loop()
    asyncio.set_event_loop(loop)
    coro = loop.create_server(RpcProtocol, '127.0.0.1', 8888)
    loop.run_until_complete(coro)
    loop.run_forever()
    loop.close()
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы