Understanding greenlet
-
Upload
saul-ibarra-corretge -
Category
Technology
-
view
1.609 -
download
0
description
Transcript of Understanding greenlet
Understanding greenletSaúl Ibarra Corretgé - @saghul
Amsterdam Python Meetup Group
Quick check
Gevent or Eventlet, anyone?
Who knows what greenlet is?
Who has used it (standalone)?
Who understands how it works?
Greenlet
Micro-threads with no implicit scheduling
Lightweight
Only one can run at a time
Cooperative
Greenlet APIgreenlet(func, parent=None): creates a greenlet to run ‘func’
greenlet.switch(*args, **kw): switches execution to the target greenlet, the first timefunc(*args, **kw) will be executed
greenlet.throw([typ, [val, [tb]]]): switches execution to the target greenlet and raises the specified exception (GreenletExit by default)
Exampleimport greenlet
main = greenlet.getcurrent()
def foo(n): main.switch(n)
def bar(n): foo(n) return 'hello'
g1 = greenlet.greenlet(bar)print g1.switch(42) # 42print g1.switch() # 'hello'print g1.dead # True
How does it work?
Organized in a tree structure
Each greenlet has a ‘parent’, except main
When a greenlet dies, control is switched to its parent
Execution order isn’t always obvious
A glorified GOTO?!
How does it work? (II)
greenlet1greenlet2
greenlet3
greenlet4greenlet5
How does it work? (III)‘Stack switching’
Non portable asm code
Copy stack slices on the heap
State is saved and restored when switching
CPU registers
Current Python frame, recursion depth and exception state
Enter PyPy
New shiny and fast implementation of Python
Vast amount of fairy-dust covered unicorns included
Includes an implementation of greenlet
Implemented on top of “continulet” objects
import _continuation
Continulets are one-shot continuations
Switching code is a standalone C library: stacklet
rpython/translator/c/src/stacklet/
Continulet APIcontinulet(func, *args, **kw): create a continulet object which will call fun(cont, *args, **kw)
continulet.switch(value=None, to=None): start the continulet or activate the previously suspended one. If to is specified a ‘double switch’ is performed
continulet.throw(type, value=None, tb=None, to=None): similar to switch, but raise the given exception after the switch is done
Stacklet
Tiny library implementing one-shot continuations for C
Single C file (~400 lines) + per-platform asm
Supports x86, x86_64 and ARM
Nice and simple API
Stacklet API
stacklet_newthread(): creates a new thread handle
stacklet_new(thread_handle, run_func, run_arg): calls run(arg) in a new stacklet, starts immediately
stacklet_switch(target): switches execution to target stacklet
Example#include <assert.h>#include "stacklet.h"
static stacklet_thread_handle thrd;
stacklet_handle empty_callback(stacklet_handle h, void *arg){ assert(arg == (void *)123); return h;}
void test_new(void){ stacklet_handle h = stacklet_new(thrd, empty_callback, (void *)123); assert(h == EMPTY_STACKLET_HANDLE);}
int main(int argc, char **argv){ thrd = stacklet_newthread(); test_new(); stacklet_deletethread(thrd); return 0;}
The Stacklet Sandwich (TM)
stacklet
continulet
greenlet
Using greenletToo low level, it’s usually used through a framework
gevent, eventlet, evergreen *, gruvi *, ...
In these frameworks, switching happens through a “hub”
*: these frameworks use python-fibers now
Using greenlet (II)main hub
g1 g2 g3 ...
Undoing callbacksimport greenlet
# ...
def foo_async(cb): call cb(result, error) eventually pass
def foo_sync(): current = greenlet.getcurrent() def cb(result, error): if error is not None: current.throw(Exception(error)) else: current.switch(result) foo_async(cb) return hub.switch()
import fibersMicro-threadling library API inspired by Python threads and greenlet
Uses stacklet underneath
Works on CPython and PyPy
On PyPy it uses continulets
github.com/saghul/python-fibers
Or pip install fibers
shameless plug!
Questions?
bettercallsaghul.com@saghul