Repository navigation
gh-160760: asyncio: run newly scheduled callbacks eagerly before polling for I/O #145149
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
base: main
Are you sure you want to change the base?
Changes from all commits
917f47b
da8dd93
136a126
a192396
78f7944
274c8b7
6e80869
28c388c
1959912
c0832da
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -33,6 +33,17 @@ | |
| # Default timeout for joining the threads in the threadpool | ||
| THREAD_JOIN_TIMEOUT = 300 | ||
|
|
||
| # Maximum number of callbacks run during eager processing between checks | ||
| # of the eager_max_time deadline. A batch also ends where the callbacks | ||
| # scheduled during it begin, so for chains of callbacks the deadline is | ||
| # checked after every callback. | ||
| EAGER_BATCH_SIZE = 100 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does adding the constant
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe it increases the code readability. But constants are not publicly exposed; it is internal change only. |
||
|
|
||
| # Values of BaseEventLoop._eager_state other than a number of callbacks. | ||
| EAGER_IDLE = -1 | ||
| # Set by asyncio.sleep(0) to end eager processing. | ||
| EAGER_BREAK = -2 | ||
|
|
||
| # The enum should be here to break circular dependencies between | ||
| # base_events and sslproto | ||
| class _SendfileMode(enum.Enum): | ||
|
|
||
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 don't understand why this test is present here.
Uh oh!
There was an error while loading. Please reload this page.
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.
_readyhandlers because of limits.loop.stop()was not called.loop.stop()run_until_complete()logic, we should stop the iteration after executing callbacks from this pack and stop. If we remove the check, extra callbacks (timers, I/O) could be called. It doesn't change any pre-existing tests but behaves a little differently than the 'main' version.Because of this, I've preferred to keep this check and add a test for pinning the behavior.
Uh oh!
There was an error while loading. Please reload this page.
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.
Thank for the explanation, I forgot the previous iteration. Last question: I wonder why the
self._eager_stateattr is not update withntodo - nleftbefore thereturnstatement as you do it in line 2110 and 2129.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.
Good question, thanks!
The PR keeps a negative (-1 or -2)
_eager_stateon a purpose.If we stored a count,
run_forever()would see_stopping and _eager_state >= 0and run the extra final_run_once()(https://github.com/python/cpython/pull/145149/files#diff-7962e1627bc1bfbce13bef0be78d5ef7fc962f99bbc524a199ef489852ca1344R689). That would run callbacks from the next iteration, which breaks a code that relies on existingrun_until_complete()behavior.With negative
_eager_state,run_forever()just breaks. The remaining callbacks stay queued and run the next time the loop runs.Uh oh!
There was an error while loading. Please reload this page.
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.
Thanks for your reply. It was hard for me to understand how
self._state_eagercan behave sometimes as a state and sometimes as a counter. Everything is clear to me now.