Guido van Rossum added the comment:

AFAICT the changes to selectmodule.c have been rolled back, both in the 3.3 and 
the 3.4 (default) branches. That takes care of backwards compatibility. :-)

So what we're talking about is whether (a) the selectors module (new in 3.3) 
should export a resolution property and what asyncio should do.

The selectors module in the repo does export a resolution property. It is 1 
usec for select, 1msec for poll and epoll, and 1 nsec for kqueue. AFAIK these 
values are derived from the data type and scale used by the corresponding 
syscall.

The latest code in the asyncio module uses that resolution for exactly one 
purpose: if, after waking up from a selector.select() call, any events we are 
waiting for are less than the resolution in the future, we consider them ready.

I like this approach -- it trusts the syscall to do approximately the right 
thing most of the time, but it doesn't fall into the busy-wait trap. This trap 
is especially egregious for [e]poll, where the timing resolution is limited to 
1 msec due to the syscall interface.

To explain the trap once more: suppose you have an event scheduled 0.9 msec in 
the future. Because of the 1 msec resolution of the [e]poll syscall API, the 
syscall is made with an argument of 0, which means it returns (almost) 
immediately. Given a fast CPU and no other IO ready, this might well take only 
a few usec. So the event loop does essentially nothing and then comes back to 
the poll call. The same event is now e.g. 0.89 msec in the future. So we call 
[e]poll with a timeout of 0 again, and we keep going around without ever 
releasing the CPU for the full 0.9 msec -- which nowadays is serious time in 
which a lot of other, more useful things could be accomplished by other threads 
or processes.

I think what's currently in the repo is all a fine solution to all that. 
Because the resolution is specified on a per-selector-class basis, we 
compensate appropriately for [e]poll but don't apply such a coarse granularity 
to the other syscalls, which are (potentially) more accurate.

If in the future we find that on some systems the kernel systematically rounds 
the timeout down using some coarser clock resolution we can add a 
system-specific compensation to the selectors module, and asyncio itself 
doesn't have to worry about it. (Though I personally don't expect we'll find 
this behavior.)

One final comment: IIUC the earlier fix involved using ceil() and other 
cleverness was essentially trying to predict *when* the next tick would wake us 
up, assuming that if the resolution is R, the kernel would wake us up at times 
that are integral multiples of R since the clock epoch. I don't think we can 
assume this at all, so I'm glad Victor rolled that back. :-)

----------

_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue20311>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to