-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
uasyncio fast_io EventLoop option reduces I/O scheduling latency #287
base: master
Are you sure you want to change the base?
Conversation
To add to this the I/O latency of the current code is twice as long as might be expected. Assume there are N coros which issue The reason for this is as follows. Assume user coros as per the test script like async def dummy(self):
while True:
await asyncio.sleep(0)
utime.sleep_ms(10) # Emulate time consuming user code Assume an initial condition where the run queue contains N such coros. Each will be scheduled before the scheduler's So in the next iteration through the run queue the N coros run a second time before the I/O read is re-scheduled. At the time when this takes place each coro has yielded and been put on the run queue. So after the I/O read has been scheduled the run queue contains the N coros recreating the assumed initial condition. This PR does not alter this default behaviour. But when |
From my understanding there are two main things going on here: 1) implementing priorities for coros (low and high); 2) pumping the IO poller faster to give high-priority IO a chance to schedule itself faster. For part 1): would it be simpler to just push the callback to the head of the runq, rather than having a separate queue? Also, it seems the way to specify that the coro has priority here is to make it yield IOReadDone/IOWriteDone (via the appropriate StreamReader/StreamWriter class). Might there not be a more general way to specify that a coro is higher priority, like registering itself as high-prio with the event loop? |
My initial plan was indeed to push the coro to the head of The inner loop runs only those tasks which were on The forthcoming fix for the read/write class bug means that the I/O coros register themselves as high priority by ._call_io which places them on I'm unsure what you're suggesting regarding a more general solution. |
This PR offers a solution to the issue discussed in MicroPython issue 2664 and provides a way of accessing the full capability of MicroPython PR 3836; namely the ability to support user-written stream I/O drivers with low latency.
An optional
ioq_len=0
arg toget_event_loop()
is added. The default behaviour is unchanged from standard: if I/O is pending in the presence of coros on the run queue, the I/O task is appended to the run queue and is scheduled after all pending tasks have yielded.If
ioq_len
is > 0, pending I/O tasks will be scheduled in preference to tasks on the run queue, substantially reducing latency. This reduces the need for buffering of fast I/O devices and improves the response time of user-written I/O drivers.A test program demonstrating this effect may be found here.