Skip to content
Advertisement

Are there any deliberately unfair (LIFO) synchronisation constructs within Python async?

I’m looking for a way to rate limit a recursive algorithm. To demonstrate the problem I’ll use the example of exploring a directory tree:

JavaScript

The problem with this code is the way the number of active tasks explode exponentially. Many of these tasks hold OS resources, so even though tasks themselves are theoretically cheap, running millions simultaneously is going to cause problems. Yet we don’t want to run one task at a time (without gather) because there is a significant performance boost from running these tasks in parallel.

Python’s async Semaphore is first in first out. Python’s async Lock is first in first out and its semaphore is mostly first in first out except for a race condition. This leads the exploration to be approximately breadth first and the number of tasks explodes into millions even if most of them are waiting. As described, this is still causing problems and not fixing the root cause.


One example error from this is IOError: [Errno 24] Too many open files. Obviously it’s possible to put limits around opening files via semaphores. But then this shift the problem onto other resources and we end up playing “wack a mole” with individual resource limits.


What I’m hunting for is something like a semaphore that is deliberately unfair and subject to starvation. I want a semaphore that imposes last-in-first-out instead of first-in-first-out. The aim is to use the resource constraints to squeeze the exploration into a more depth-first pattern instead of breadth-first.

Advertisement

Answer

To my surprise python’s semaphore is not fair. There’s a race condition which gives priority to new calls to acquire() over tasks which have been released but not yet executed on the event loop. That is:

JavaScript

Irrespective of the number of waiting tasks, the above code will never block and will even re-order the queue of waiting tasks as a result. So sadly this object is useless for enforcing a strict order.

I wrote my own:

JavaScript
User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement