I've looked all over the documentation, but could not find it.
Suppose multiple await calls are done, and their coroutines are all ready to be resumed, what algorithm does asyncio's event loop use to decide which coroutine gets resumed?
I've looked all over the documentation, but could not find it.
Suppose multiple await calls are done, and their coroutines are all ready to be resumed, what algorithm does asyncio's event loop use to decide which coroutine gets resumed?
1) Documentation shows us that event loop starts with run_forever / run_until_complete. We need to find source code of function(s) to see what happens next.
2) The Fastest way (I know) to do it is to search relevant name on github. Go to github.com/python/cpython, use search form on top-left:
Github will show you all occurrences in project. Make sure you search in code:
3) We need implementation, there are two of them found: one inside ProactorEventLoop where nothing interesting happens since it partly reimplement parent event loop; and one inside BaseEventLoop and it seems to be what we search for.
4) Let's examine the code. Pretty soon we'll see that everything comes to calling _run_once inside while True loop:
try:
events._set_running_loop(self)
while True:
self._run_once()
if self._stopping:
break
5) Let's go to _run_once (we can just search def _run_once on the page). Here's where scheduled things get resumed. There're two interesting places you'll see going through source code:
event_list = self._selector.select(timeout) - it is where asyncio sleeps until activity on sockets. You can investigate this mechanism further reading documentation. But this place doesn't resume coroutines itself.This is the only place where callbacks are actually *called*. All other places just add them to ready.Exactly what we searched for. You can read source code there (and inside _run_once function in general) to see how callbacks are executed and how they are added to self._ready to be executed. Callbacks includes ones added directly and ones asyncio uses internally to resume coroutines.
You can also reimplement event loop to play with it. Take a look at code here, it contains example of event loop reimplementing.
Few notes:
BaseEventLoop, other event loops like custom uvloop may do something different.