[Python-ideas] Tulip / PEP 3156 event loop implementation question: CPU vs. I/O starvation (original) (raw)

Jan Kaliszewski zuo at chopin.edu.pl
Sat Jan 12 02:28:25 CET 2013


12.01.2013 00:41, Guido van Rossum wrote:

Here's an interesting puzzle. Check out the core of Tulip's event loop: http://code.google.com/p/tulip/source/browse/tulip/unixevents.py#672

Specifically this does something like this: 1. poll for I/O, appending any ready handlers to the ready queue 2. append any handlers scheduled for a time <= now to the ready queue 3. while ready: handler = ready.popleft() call handler It is the latter loop that causes me some concern. In theory it is possible for a bad callback to make this loop never finish, as follows: def hogger(): tulip.geteventloop().callsoon(hogger) Because callsoon() appends the handler to the ready queue, the while loop will never finish. There is a simple enough solution (Tornado uses this AFAIK): nowready = list(ready) ready.clear() for handler in nowready: call handler However this implies that we go back to the I/O polling code more frequently. While the I/O polling code sets the timeout to zero when there's anything in the ready queue, so it won't block, it still isn't free; it's an expensive system call that we'd like to put off until we have nothing better to do. [...] So what's more important? Avoid I/O starvation at all cost or make the callbacks-posting-callbacks pattern efficient? I can see several outcomes of this discussion: we could end up deciding that one or the other strategy is always best; we could also leave it up to the implementation (but then I still would want guidance for what to do in Tulip); we could even decide this is so important that the user needs to be able to control the policy here [...]

Maybe it could be, at least for the standard Tulip implementation, parameterizable with a simple integer value -- the suggested max number of loop iterations?

E.g. something like the following:

 # `suggested_iter_limit` is the parameter
 actual_limit = max(len(_ready), suggested_iter_limit)
 for i in range(actual_limit):
     if not _ready:
         break
     handler = _ready.popleft()
     call handler...

Regards. *j



More information about the Python-ideas mailing list