[openstack-dev] Asynchrounous programming: replace eventlet with asyncio

Victor Stinner victor.stinner at enovance.com
Fri Feb 7 22:59:34 UTC 2014


Le mardi 4 février 2014, 12:53:24 Kevin Conway a écrit :
> One of the great benefits of using a green thread abstraction, like
> eventlet or gevent, is that it lets you write normal Python code and slap
> your concurrency management over the top. It even lets us program in
> familiar models by pretending like we are using threads.

Using Tulip/Trollius, thanks to yield-from/yield, the code a function is 
sequential. So it's very close to eventlet programming if you ignore 
yield/yield from in the code.

Basically, just replace "data = obj.read(10)" with "data = yield 
obj.read(10)".

> Switching our async IO management from eventlet to asyncio would not be a
> trivial task. Tell me when I'm wrong, but it would require that we
> completely change our programming model from typical, function-call based
> programming to use generator-iterators for everything.

No, that's wrong. The only functions that will need to be made asynchronous 
are all functions which are performance critical. Examples: HTTP query to a 
server or request to a database. All other code will be left unchanged.

I don't see why external libraries should be modified. Only the few libraries 
sending HTTP queries and requests to the database should handle asyncio. Dummy 
example: the iso8601 module used to parse time doesn't need to be aware of 
asyncio.

***

I don't know OpenStack well enough to say how much code should be modified, but 
I guess that only few functions need to be modified to be asynchronous.

Dummy example:
---
def task():
    print("hello")
    time.sleep(1)
    print("world")
---

With eventlet and monkey-patching, this task is suspended and other tasks can 
be executed before "world" is displayed.

With eventlet without monkey-patching orwith asyncio: this function will block 
for 1 second.

To make this function asynchronous and allow other tasks to run during the 
sleep, you have to write:
---
@asyncio.coroutine
def task():
    print("hello")
    yield from asyncio.sleep(1)
    print("world")
---

But you will also have to modify how the function is called.

Victor



More information about the OpenStack-dev mailing list