[ANN] uasyncio - lean asyncio-like library

Paul Sokolovsky pmiscml at gmail.com
Sun Jun 28 23:29:22 CEST 2015


Hello,

It was mentioned several times on the list already, and I would
like to finally make a formal announcement of it, also to mark "mostly
complete" status.

What:
uasyncio is asyncio-like library for MicroPython
(https://github.com/micropython/micropython) to accommodate writing
asyncio-style applications for constrained (both memory- and CPU-wise)
systems, down to microcontrollers, but also for small embedded Linux
systems (as well as for embedding into non-Python applications, or
producing small self-contained applications).

Where:
https://github.com/micropython/micropython-lib/tree/master/uasyncio.core
https://github.com/micropython/micropython-lib/tree/master/uasyncio

Structure:
uasyncio is structured as 2 components: uasyncio.core module which
implements generic priority queue based scheduler, and uasyncio package
proper, which adds async I/O support (currently with Linux support).

Functionality provided:
uasyncio implements subset of asyncio functionality:
1. It is built around concept of coroutines. Future's and Task's are
not part of its core API.
2. For I/O, high-level Stream API is supported, without low-level
Transport API.

Differences from asyncio:
1. The main difference is that uasyncio is strictly asynchronous
library, with writing (and other related operations) being as
asynchronous as read. More info is in http://bugs.python.org/issue24449
which also links to recent discussion on the list.

2. One potential difference is handling of Stream close operations.
This aspect isn't yet fully worked out (and is the reason why I didn't
post uasyncio announcement earlier). Intuitively, the issue is that
asyncio separate read and write Streams into separate objects. But
underlying socket object is a duplex read/write one, so closing it
should be done carefully. As uasyncio tries to avoid extra abstraction
layers, its handling of close operations is different to that of
asyncio. Any hints/discussion of this issue is welcome.

3. As an extension, it's possible to schedule a new coroutine for
execution by just yielding it. This was also discussed previously at
http://comments.gmane.org/gmane.comp.python.tulip/2430 .

To let uasyncio applications run with asyncio, there's a compatibility
module available at
https://github.com/micropython/micropython-lib/tree/master/cpython-uasyncio


Ecosystem:

An experimental web stack was prototyped on top of uasyncio:

1. picoweb web pico-framework: https://github.com/pfalcon/picoweb
2. utemplate tiny template module: https://github.com/pfalcon/utemplate
3. uorm tiny anti-ORM (current implementation supports Sqlite and
actually synchronous so far): https://github.com/pfalcon/uorm

Also, there's an async HTTP client
https://github.com/pfalcon/micropython-uaiohttpclient (roughly
following aiohttp API).

There's an example application for picoweb ported from Flask:
https://github.com/pfalcon/notes-pico

Having MicroPython installed, the test app can be installed/run with:

micropython -m upip install notes-pico
micropython -X heapsize=150wK -m notes_pico.main


Achieved memory efficiency:
I once read an article which described coolness of Python coroutines,
in particular mentioning that a coroutine object takes a "mere" 1KB of
memory, so there can easily be tens of thousands of them, unlike
(preemptive) threads. In MicroPython, a small coroutine takes 32 bytes
of memory. But a minimal web application using picoweb still requires
50KB of heap to run. That's good enough for Linux systems, but somewhat
on bigger side for microcontrollers (for comparison, reference
microcontroller system for uPy has 128KB of heap; we would like to
support systems down to 16KB of memory).

Achieved performance:
Testcases are in
https://github.com/micropython/micropython-lib/tree/master/uasyncio/benchmark

uasyncio + MicroPython:
Document Length:        12000 bytes
Concurrency Level:      100
Complete requests:      10000
Requests per second:    10699.74 [#/sec] (mean)
Time per request:       9.346 [ms] (mean)

asyncio + cpython-uasyncio + CPython 3.4.2
Document Length:        12000 bytes
Concurrency Level:      100
Complete requests:      10000
Requests per second:    4876.02 [#/sec] (mean)
Time per request:       20.509 [ms] (mean)

Apache 2.4 + default static page
Document Length:        11510 bytes
Concurrency Level:      100
Complete requests:      10000
Requests per second:    12857.98 [#/sec] (mean)
Time per request:       7.777 [ms] (mean)


-- 
Best regards,
 Paul                          mailto:pmiscml at gmail.com


More information about the Python-announce-list mailing list