An eager way to set_result on asyncio.Future?

Next somebody will ask for the eager version of Queue.get() and so on.

I’m inclined to think that we are going in the wrong direction.

Let’s change a mind.
What do we really need? Execute callbacks scheduled by loop.call_soon() at the same loop iteration without calling a relatively expensive epoll() call (I’ll speak for Linux, other platforms doesn’t change the overall picture).

Now event loop works like this:

  1. There is _ready list of callbacks scheduled by loop.call_soon() on the previous iteration (maybe the list is empty).
  2. Handle ready file descriptors, add corresponding callbacks to _ready.
  3. Handle expired time handlers, add corresponding callbacks to _ready.
  4. Process all callback handlers from _ready list once: manage network activity, run tasks, etc.

We can process newly added callbacks in the same loop iteration without waiting for the next loop._run_once() call.
The blind execution of all handles from _ready list could lead to network starvation and even infinite loop if the executed callback schedules itself for the next iteration.

On my laptop (Linux), getting the current time is extremely fast; it is in the order of magnitude of a regular integer operation.
Thus, we can repeat callback execution from _ready list in a loop until there are items to process and the total processing time is less than some (very low) threshold.

Decades ago time() call was much more expensive, but I believe nowadays all modern OSes have required optimizations already. Sure, we can invent some heuristics for a number of iterations and the amount of handled callbacks in each iteration – but if time() is so cheap I don’t see any reason to do it; the direct period of execution time works better.

By adding post-execution step we can eliminate performance degradation for described situations, as well as for systems that have a cascade of processor units that communicate via asyncio queues – all will be handled on the same loop iteration until the total processing time is moderate.
As a side effect, regular tasks execute immediately after creation, but without breaking asyncio assumptions like eager tasks do.

@Tinche do you see any hidden problem with the proposal?

1 Like