Skip to content

Commit f82cbaa

Browse files
committed
Doc improvements.
1 parent bc278d2 commit f82cbaa

File tree

4 files changed

+83
-55
lines changed

4 files changed

+83
-55
lines changed

FASTPOLL.md

Lines changed: 44 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,19 @@
11
# fast_io: A modified version of uasyncio
22

3-
MicroPython firmware now enables device drivers for stream devices to be
4-
written in Python, via `uio.IOBase`. This mechanism can be applied to any
5-
situation where a piece of hardware or an asynchronously set flag needs to be
6-
polled. Such polling is efficient because it is handled in C using
7-
`select.poll`, and because the coroutine accessing the device is descheduled
8-
until polling succeeds.
9-
10-
Unfortunately official `uasyncio` polls I/O with a relatively high degree of
11-
latency. It also has a bug whereby bidirectional devices such as UARTS can
12-
fail to handle concurrent input and output.
3+
This version is a "drop in" replacement for official `uasyncio`. Existing
4+
applications should run under it unchanged and with essentially identical
5+
performance.
136

14-
This version has the following changes:
7+
This version has the following features:
158
* I/O can optionally be handled at a higher priority than other coroutines
169
[PR287](https://github.com/micropython/micropython-lib/pull/287).
1710
* Tasks can yield with low priority, running when nothing else is pending.
1811
* Callbacks can similarly be scheduled with low priority.
19-
* The bug with read/write device drivers is fixed.
12+
* A [bug](https://github.com/micropython/micropython/pull/3836#issuecomment-397317408)
13+
whereby bidirectional devices such as UARTS can fail to handle concurrent
14+
input and output is fixed.
15+
* It is compatible with `rtc_time.py` for micro-power applications documented
16+
[here](./lowpower/README.md).
2017
* An assertion failure is produced if `create_task` or `run_until_complete`
2118
is called with a generator function
2219
[PR292](https://github.com/micropython/micropython-lib/pull/292). This traps
@@ -34,13 +31,8 @@ version.
3431
The high priority mechanism formerly provided in `asyncio_priority.py` was a
3532
workround based on the view that stream I/O written in Python would remain
3633
unsupported. This is now available so `asyncio_priority.py` is obsolete and
37-
should be deleted from your system.
38-
39-
The facility for low priority coros formerly provided by `asyncio_priority.py`
40-
is now implemented.
41-
42-
This version also provides for ultra low power consumption using a module
43-
documented [here](./lowpower/README.md).
34+
should be deleted from your system. The facility for low priority coros
35+
formerly provided by `asyncio_priority.py` is now implemented.
4436

4537
###### [Main README](./README.md)
4638

@@ -61,6 +53,7 @@ documented [here](./lowpower/README.md).
6153
3.5 [Low priority callbacks](./FASTPOLL.md#35-low-priority-callbacks)
6254
4. [ESP Platforms](./FASTPOLL.md#4-esp-platforms)
6355
5. [Background](./FASTPOLL.md#4-background)
56+
6. [Performance](./FASTPOLL.md#6-performance)
6457

6558
# 1. Installation
6659

@@ -104,6 +97,16 @@ be run against the official and priority versions of usayncio.
10497

10598
# 2. Rationale
10699

100+
MicroPython firmware now enables device drivers for stream devices to be
101+
written in Python, via `uio.IOBase`. This mechanism can be applied to any
102+
situation where a piece of hardware or an asynchronously set flag needs to be
103+
polled. Such polling is efficient because it is handled in C using
104+
`select.poll`, and because the coroutine accessing the device is descheduled
105+
until polling succeeds.
106+
107+
Unfortunately official `uasyncio` polls I/O with a relatively high degree of
108+
latency.
109+
107110
Applications may need to poll a hardware device or a flag set by an interrupt
108111
service routine (ISR). An overrun may occur if the scheduling of the polling
109112
coroutine (coro) is subject to excessive latency. Fast devices with interrupt
@@ -454,3 +457,25 @@ fast scheduling took place
454457
[in issue 2664](https://github.com/micropython/micropython/issues/2664).
455458

456459
Support was finally [added here](https://github.com/micropython/micropython/pull/3836).
460+
461+
# 6. Performance
462+
463+
This version is designed to enable existing applications to run without change
464+
to code and to minimise the effect on raw scheduler performance in the case
465+
where the added functionality is unused.
466+
467+
The benchmark `rate.py` measures the rate at which tasks can be scheduled. It
468+
was run (on a Pyboard V1.1) under official `uasyncio` V2, then under this
469+
version. The benchmark `rate_fastio` is identical except it instantiates an I/O
470+
queue and a low priority queue. Results were as follows.
471+
472+
| Script | Uasyncio version | Period (100 coros) | Overhead |
473+
| --- | --- | --- |
474+
| rate | Official V2 | 156μs | 0% |
475+
| rate | fast_io | 162μs | 3.4% |
476+
| rate_fastio | fast_io | 206μs | 32% |
477+
478+
If an I/O queue is instantiated I/O is polled on every scheduler iteration
479+
(that is its purpose). Consequently there is a significant overhead. In
480+
practice the overhead will increase with the number of I/O devices being
481+
polled and will be determined by the efficiency of their `ioctl` methods.

README.md

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
# 1. The MicroPython uasyncio library
22

3-
This GitHub repository consists of the following parts. Firstly a modified
4-
`fast_io` version of `uasyncio` offering some benefits over the official
5-
version.
3+
This repository comprises the following parts.
4+
1. A modified [fast_io](./FASTPOLL.md) version of `uasyncio`. This is a "drop
5+
in" replacement for the official version providing additional functionality.
6+
2. A module enabling the `fast_io` version to run with very low power draw.
7+
3. Resources for users of official or `fast_io` versions:
68

7-
Secondly the following resources relevant to users of official or `fast_io`
8-
versions:
99
* [A tutorial](./TUTORIAL.md) An introductory tutorial on asynchronous
10-
programming and the use of the uasyncio library (asyncio subset).
10+
programming and the use of the `uasyncio` library (asyncio subset).
1111
* [Asynchronous device drivers](./DRIVERS.md). A module providing drivers for
1212
devices such as switches and pushbuttons.
1313
* [Synchronisation primitives](./PRIMITIVES.md). Provides commonly used
@@ -29,34 +29,9 @@ versions:
2929
* [Under the hood](./UNDER_THE_HOOD.md) A guide to help understand the
3030
`uasyncio` code. For scheduler geeks and those wishing to modify `uasyncio`.
3131

32-
## 1.1 The "fast_io" version.
33-
34-
This repo included `asyncio_priority.py` which is now deprecated. Its primary
35-
purpose was to provide a means of servicing fast hardware devices by means of
36-
coroutines running at a high priority. The official firmware now includes
37-
[this major improvement](https://github.com/micropython/micropython/pull/3836)
38-
which offers a much more efficient way of achieving this end. The tutorial has
39-
details of how to use this.
40-
41-
The current `uasyncio` suffers from high levels of latency when scheduling I/O
42-
in typical applications. It also has an issue which can cause bidirectional
43-
devices such as UART's to block.
44-
45-
A modified version of `uasyncio` is described [here](./FASTPOLL.md) which
46-
provides an option for I/O scheduling with much reduced latency. It also fixes
47-
the bug. It is hoped that these changes will be accepted into mainstream in due
48-
course.
49-
50-
### 1.1.1 A Pyboard-only low power version
51-
52-
This is documented [here](./lowpower/README.md). In essence a Python file is
53-
placed on the device which configures the `fast_io` version of `uasyncio` to
54-
reduce power consumption at times when it is not busy. This provides a means of
55-
using the library on battery powered projects.
56-
5732
# 2. Version and installation of uasyncio
5833

59-
The documentation and code in this repository are based on `uasyncio` version
34+
The documentation and code in this repository assume `uasyncio` version
6035
2.0, which is the version on PyPi and in the official micropython-lib. This
6136
requires firmware dated 22nd Feb 2018 or later. Use of the stream I/O mechanism
6237
requires firmware after 17th June 2018.
@@ -114,7 +89,32 @@ The `loop.time` method returns an integer number of milliseconds whereas
11489
CPython returns a floating point number of seconds. `call_at` follows the
11590
same convention.
11691

117-
# 4. The asyn.py library
92+
# 4. The "fast_io" version.
93+
94+
Official `uasyncio` suffers from high levels of latency when scheduling I/O in
95+
typical applications. It also has an issue which can cause bidirectional
96+
devices such as UART's to block. The `fast_io` version fixes the bug. It also
97+
provides a facility for reducing I/O latency which can substantially improve
98+
the performance of stream I/O drivers. It provides other features aimed at
99+
providing greater control over scheduling behaviour.
100+
101+
## 4.1 A Pyboard-only low power module
102+
103+
This is documented [here](./lowpower/README.md). In essence a Python file is
104+
placed on the device which configures the `fast_io` version of `uasyncio` to
105+
reduce power consumption at times when it is not busy. This provides a means of
106+
using `uasyncio` in battery powered projects.
107+
108+
## 4.2 Historical note
109+
110+
This repo formerly included `asyncio_priority.py` which is replaced. Its main
111+
purpose was to provide a means of servicing fast hardware devices by means of
112+
coroutines running at a high priority. The official firmware now includes
113+
[this major improvement](https://github.com/micropython/micropython/pull/3836)
114+
which offers a much more efficient way of achieving this end. The tutorial has
115+
details of how to use this.
116+
117+
# 5. The asyn.py library
118118

119119
This library ([docs](./PRIMITIVES.md)) provides 'micro' implementations of the
120120
`asyncio` synchronisation primitives.

benchmarks/rate.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
# This measures the rate at which uasyncio can schedule a minimal coro which
44
# mereley increments a global.
55

6-
# Outcome: minimal coros are scheduled at an interval of ~150us
6+
# Outcome: 100 minimal coros are scheduled at an interval of ~156μs on official
7+
# uasyncio V2. On fast_io version 0.1 (including low priority) at 162μs.
8+
# fast_io overhead is < 4%
79

810
import uasyncio as asyncio
911

benchmarks/rate_fastio.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
# This measures the rate at which uasyncio can schedule a minimal coro which
55
# mereley increments a global.
66

7-
# Outcome: minimal coros are scheduled at an interval of ~200us
7+
# This is identical to rate.py but instantiates io and lp queues
8+
# Outcome: minimal coros are scheduled at an interval of ~206μs
89

910
import uasyncio as asyncio
1011

@@ -41,7 +42,7 @@ async def test():
4142
done = True
4243

4344
ntasks = max(num_coros) + 2
44-
loop = asyncio.get_event_loop(ntasks, ntasks, 6)
45+
loop = asyncio.get_event_loop(ntasks, ntasks, 6, 6)
4546
loop.create_task(test())
4647
loop.run_until_complete(report())
4748

0 commit comments

Comments
 (0)