Skip to content
This repository has been archived by the owner. It is now read-only.

Round timeout in BaseEventLoop._run_once() #106

Closed
GoogleCodeExporter opened this issue Apr 10, 2015 · 2 comments
Closed

Round timeout in BaseEventLoop._run_once() #106

GoogleCodeExporter opened this issue Apr 10, 2015 · 2 comments

Comments

@GoogleCodeExporter
Copy link

@GoogleCodeExporter GoogleCodeExporter commented Apr 10, 2015

Hi, I tried to compare Tulip and Trollius, to try to understand how "yield 
from" is different from "yield". I wrote the following script:
https://bitbucket.org/haypo/asyncio_staging/src/47a0b9c/event_loop_run_once.py

When I replaced asyncio.sleep(1.0) with asyncio.sleep(0.1), I saw more than 50 
calls to _run_once() wheras only 4 calls are required with a sleep of one 
second.

Example with a sleep of 100 milliseconds:
- Tulip computes a deadline of 99.98 milliseconds, epoll_wait() is called with 
a timeout of 99 ms
- Timeout, but the scheduled task is not scheduled because there is still a 
difference of 0.6 milliseconds
- Tulip computes a deadline of 0.47 ms, epoll_wait() is called with a timeout 
of... 0 ms
- Timeout, but the scheduled task is not scheduled because there is still a 
difference of... 0.3 milliseconds
- etc. until the timeout is reached

The number of iterations depends on the speed of your CPU. For example, a dummy 
loop calling sleep(1e-3) ten times calls _run_once() 918 times on my laptop...

The problem is that the C function epoll_wait() expects a C int for the 
timeout, which is a number of milliseconds. So 99.98 ms should be rounded to 
*100* ms, and 0.47 ms must be rounded to 1 ms.

In my opinion, it's a bug in CPython: epoll.poll(timeout) should wait *at 
least* timeout seconds, but not *less*.

I reported the issue in CPython:
http://bugs.python.org/issue20311

Even if the bug in fixed in Python 3.4 and the next release of Python 3.3, 
Tulip should works around this bug to support older Python 3.3 released.

Attached patch should fix the issue.

Original issue reported on code.google.com by victor.s...@gmail.com on 20 Jan 2014 at 10:52

Attachments:

@GoogleCodeExporter

This comment has been minimized.

Copy link
Author

@GoogleCodeExporter GoogleCodeExporter commented Apr 10, 2015

selectors.PollSelector() has a similar bug. New patch: 
poll_epoll_workaround.patch.

The new patch is simpler, it doesn't touch event loops, only the selectors 
module.

I removed the try/except ImportError on "from . import selectors" because I 
don't understand how this import can fail, and to get a more reliable behaviour 
(always use asyncio/selectors.py).

Original comment by victor.s...@gmail.com on 20 Jan 2014 at 2:18

Attachments:

@GoogleCodeExporter

This comment has been minimized.

Copy link
Author

@GoogleCodeExporter GoogleCodeExporter commented Apr 10, 2015

I fixed the timeout rouding issue bug of poll and epoll in Python 3.3 and 3.4:
http://bugs.python.org/issue20311

In fact, select and kqueue have also rounding issue. It's less important 
because select has a resolution 1 microsecond (10^-6) and kqueue has a 
resolution of 1 nanosecond (10^-9), wheras poll and epoll have a resolution of 
1 millisecond (10^-3). I opened an issue to fix the rounding issue for select 
and kqueue in Python, but I don't think that it's necessary to work around them 
in Tulip since I'm unable to reproduce the bug with select() and Tulip.
http://bugs.python.org/issue20320

I commited my workaround for poll and epoll rounding issues in Tulip, because 
Python 3.3 is still used in the wild and has the epoll bug => changeset 
5b7e17a75ba4.

Original comment by victor.s...@gmail.com on 21 Jan 2014 at 1:34

  • Changed state: Fixed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
1 participant
You can’t perform that action at this time.