New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
asyncio.wait very slow with FIRST_COMPLETED #74741
Comments
This is best described the script at https://gist.github.com/samuelcolvin/00f01793c118bf9aafae886ffbc81a58. Basically, completing a set of tasks using asyncio.wait(...return_when=asyncio.FIRST_COMPLETED) in a loop to wait for them to finish is much much slower than completing the same set of tasks using just asyncio.wait(pending_tasks, loop=loop, return_when=asyncio.ALL_COMPLETED). In my example, the ALL_COMPLETED case takes ~5s, but the FIRST_COMPLETED case takes 18 - 47s. The screenshot on the gist shows network usage with a very long tail, in other words very few tasks are taking a long time to complete. This example uses aiohttp get a url as the test case but I'm pretty sure this isn't an issue with aiohttp. I tried the same thing with uvloop but got broadly the same result. |
I tried the script and don't see much difference in performance of import asyncio
from statistics import mean, stdev
from time import time
from aiohttp import ClientSession
request_count = 1500
url = 'https://www.wikipedia.org/'
async def main(use_first_complete=False):
loop = asyncio.get_running_loop()
print(f'using FIRST_COMPLETED: {use_first_complete}')
start_time = time()
async with ClientSession() as session:
async def run(v, _create_time):
_start_time = time()
async with session.get(url) as r:
assert r.status == 200
wait, request = _start_time - _create_time, time() - _start_time
# print(f'{v:>5} wait: {wait:0.3f}s, request: {request:0.3f}s')
return wait, request
pending_tasks = {loop.create_task(run(i, time())) for i in range(request_count)}
if use_first_complete:
complete_tasks = set()
while pending_tasks:
done, pending_tasks = await asyncio.wait(pending_tasks, return_when=asyncio.FIRST_COMPLETED)
complete_tasks.update(done)
else:
complete_tasks, pending_tasks = await asyncio.wait(pending_tasks)
assert not pending_tasks
time_taken = time() - start_time
print(f'total time taken {time_taken:0.2f}')
results = [t.result() for t in complete_tasks]
wait_times, request_times = zip(*results)
print(f'wait times: mean {mean(wait_times):0.3f}s, stdev {stdev(wait_times):0.3f}s')
print(f'request times: mean {mean(request_times):0.3f}s, stdev {stdev(request_times):0.3f}s')
asyncio.run(main(use_first_complete=False)) |
Cc. @samuelcolvin — I believe you might not be subscribed to this issue any more due to the migration to GitHub |
Closing as the bug report is very old and the implementation has changed significantly since then especially with the new rewritten ssl implementation. Create a new issue if required. |
Agreed, sorry for the noise. |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: