-
-
Notifications
You must be signed in to change notification settings - Fork 33.5k
bpo-32355: Optimize asyncio.gather() #4913
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
Conversation
| for arg in coros_or_futures: | ||
| if arg not in arg_to_fut: | ||
| fut = ensure_future(arg, loop=loop) | ||
| if loop is None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems like the check for multiple loops (see line 622) has been removed. Is this intentional?
If it is, you may want to add a test for that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ensure_future does it. No need to do it twice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ensure_future validates that the passed in loop argument matches that of the future passed in. If I were to pass 3 futures each having their own different loop, a new _GatheringFuture will be created tied to the loop that was passed to gather (which can be a separate loop as well).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I understand what you mean by that, ensure_future will make sure that the future/coro passed is bound to the same loop - either current or what was passed in. Thanks for explaining.
Lib/asyncio/tasks.py
Outdated
| for fut in children: | ||
| if fut.cancelled(): | ||
| res = futures.CancelledError() | ||
| elif fut._exception is not None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_exception and _result is not a part of Future public API
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
well, old code used it, i'm not adding anything new
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought about this for a while. Let's use only public Future API in asyncio. I've updated this PR and will make a new one to fix all remaining places in asyncio.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, it's just one other place where we access Future._exception or Future._result in asyncio -- it's base_events.py. I've fixed it as part of this PR.
| if not return_exceptions: | ||
| outer.set_exception(res) | ||
| if not return_exceptions: | ||
| if fut.cancelled(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Both checks can be merged:
exc = fut.exception()
if exc is not None:
outer.set_exception(exc)
it handles CancelledError too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no, it will raise CancelledError, not return it. We can't merge these checks.
| # Future created specifically for 'arg'. Since the caller | ||
| # can't control it, disable the "destroy pending task" | ||
| # warning. | ||
| fut._log_destroy_pending = False |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unrelated question: maybe add log_destroy_pending keyword-only parameter?
Often I want to see cancelled coroutines in logs.
I also believe the this PR makes
asyncio.gather()code simpler (besides also making it 10-15% faster).https://bugs.python.org/issue32355