我正在使用Asyncio和Requests来对一系列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
答案 0 :(得分:14)
在开始下一个请求之前,您正在等待每个请求完成。所以你有没有任何好处的事件循环的开销。
试试这个:
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
。
答案 1 :(得分:7)
为了完整起见,这是一个非常快速的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()
await session.close()
te = time.time()
print("Aiohttp version: " + str(te - ts))
loop = asyncio.get_event_loop()
loop.run_until_complete(main(10))
loop.close()
代码是python 3.5及更高版本。
~> python asyncioreq.py
200
...
Aiohttp version: 0.15974688529968262
希望有人可以使用它;)
答案 2 :(得分:3)
以@brunsgaard的回答为基础:您可以使用aiohttp更进一步,并使用asyncio.gather()
收集结果。然后,您可以从请求中获取响应并进行处理。
import aiohttp
import asyncio
import time
async def main(n):
start = time.time()
session = aiohttp.ClientSession()
jobs = [session.get('http://google.com') for _ in range(n)]
done_jobs = await asyncio.gather(*jobs)
for done_job in done_jobs:
print(done_job.status)
session.close()
end = time.time()
print("Time: " + str(end - start))
loop = asyncio.get_event_loop()
loop.run_until_complete(main(10))
loop.close()