5

Я использую Asyncio и запросы для тестирования серии HTTP-запросов.Asyncio Выполнение запросов HTTP медленнее?

По некоторым причинам, это немного медленнее, чем Asyncio, чем просто прямые запросы. Любая идея почему? Я неправильно использую Asyncio?

import asyncio 
import functools 
import requests 
import time 

ts = time.time() 
for i in range(10): 
    @asyncio.coroutine 
    def do_checks(): 
     loop = asyncio.get_event_loop() 
     req = loop.run_in_executor(None, functools.partial(requests.get, "http://google.com", timeout=3)) 
     resp = yield from req 
     print(resp.status_code) 

    loop = asyncio.get_event_loop() 
    loop.run_until_complete(do_checks()) 
te = time.time() 
print("Version A: " + str(te - ts)) 

ts = time.time() 
for i in range(10): 
    r = requests.get("http://google.com", timeout=3) 
    print(r.status_code) 
te = time.time() 

print("Version B: " + str(te - ts)) 

Выход:

Вариант A = Asyncio; Версия B = Запросы

200 
200 
200 
200 
200 
200 
200 
200 
200 
200 
Version A: 5.7215821743011475 
200 
200 
200 
200 
200 
200 
200 
200 
200 
200 
Version B: 5.320340156555176 

ответ

12

Ожидается, что каждый запрос будет завершен, прежде чем вы начнете следующую. Таким образом, у вас есть накладные расходы цикла событий без каких-либо преимуществ.

Попробуйте это:

import asyncio 
import functools 
import requests 
import time 

ts = time.time() 
loop = asyncio.get_event_loop() 

@asyncio.coroutine 
def do_checks(): 
    futures = [] 
    for i in range(10): 
     futures.append(loop.run_in_executor(None, functools.partial(requests.get, "http://google.com", timeout=3))) 

    for req in asyncio.as_completed(futures): 
     resp = yield from req 
     print(resp.status_code) 

loop.run_until_complete(do_checks()) 
te = time.time() 
print("Version A: " + str(te - ts)) 

ts = time.time() 
for i in range(10): 
    r = requests.get("http://google.com", timeout=3) 
    print(r.status_code) 
te = time.time() 
print("Version B: " + str(te - ts)) 

Это то, что я получаю, когда я запустить его:

$ python test.py 
200 
... 
Version A: 0.43438172340393066 
200 
... 
Version B: 1.6541109085083008 

Гораздо быстрее, но на самом деле это просто нерест темы и ждет библиотека HTTP, чтобы закончить, для этого вам не нужно asyncio.

Возможно, вы захотите заказать aiohttp, так как он был построен для использования с asyncio. requests - сказочная библиотека, но это не сделано для asyncio.

+0

Великий ответ, что помогает! Существуют ли какие-либо преимущества, связанные с тем, что 'asyncio' запускает потоки вместо того, чтобы делать это напрямую? – okoboko

+2

@okoboko Если вы собираетесь использовать 'запросы', нет необходимости использовать' asyncio', если у вас нет других компонентов в вашем проекте, которые на самом деле предназначены для использования с 'asyncio'. И если это так, вы должны одобрить 'aiohttp' над' запросами', если вам не нужна функция 'запросов', отсутствующая в' aiohttp'. – dano

+2

Одна нота с 'loop.run_in_executor' - при использовании исполнителя по умолчанию (путем передачи' None' в качестве первого аргумента) вы используете 'concurrent.futures.ThreadPoolExecutor' с пятью потоками. Это означает, что вы можете одновременно запускать только пять запросов, что довольно мало для рабочей нагрузки, связанной с вводом-выводом. Вероятно, вы получите лучшую производительность, если создадите свой собственный ThreadPoolExecutor с большим количеством потоков. – dano

6

Просто для полноты картины, вот это действительно быстрая реализация asyncio

import aiohttp 
import asyncio 
import time 

async def main(n): 
    ts = time.time() 
    session = aiohttp.ClientSession() 
    fs = [session.get('http://google.com') for _ in range(n)] 
    for f in asyncio.as_completed(fs): 
     resp = await f 
     print(resp.status) 
     await resp.release() 
    session.close() 
    te = time.time() 
    print("Aiohttp version: " + str(te - ts)) 

loop = asyncio.get_event_loop() 
loop.run_until_complete(main(10)) 
loop.close() 

Код питон 3.5 и выше.

~> python asyncioreq.py 
200 
... 
Aiohttp version: 0.15974688529968262 

Надежда кто-то может использовать его;)

 Смежные вопросы

  • Нет связанных вопросов^_^