Understanding greenlet

24
Understanding greenlet Saúl Ibarra Corretgé - @saghul Amsterdam Python Meetup Group

description

Slides from my talk about how greenlet works internally. Talk given at the Amsterdam Python Meetup Group.

Transcript of Understanding greenlet

Page 1: Understanding greenlet

Understanding greenletSaúl Ibarra Corretgé - @saghul

Amsterdam Python Meetup Group

Page 2: Understanding greenlet

Quick check

Gevent or Eventlet, anyone?

Who knows what greenlet is?

Who has used it (standalone)?

Who understands how it works?

Page 3: Understanding greenlet

Greenlet

Micro-threads with no implicit scheduling

Lightweight

Only one can run at a time

Cooperative

Page 4: Understanding greenlet

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)

Page 5: Understanding greenlet

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

Page 6: Understanding greenlet

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?!

Page 7: Understanding greenlet

How does it work? (II)

greenlet1greenlet2

greenlet3

greenlet4greenlet5

Page 8: Understanding greenlet

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

Page 9: Understanding greenlet
Page 10: Understanding greenlet
Page 11: Understanding greenlet
Page 12: Understanding greenlet
Page 13: Understanding greenlet

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

Page 14: Understanding greenlet

import _continuation

Continulets are one-shot continuations

Switching code is a standalone C library: stacklet

rpython/translator/c/src/stacklet/

Page 15: Understanding greenlet

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

Page 16: Understanding greenlet

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

Page 17: Understanding greenlet

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

Page 18: Understanding greenlet

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;}

Page 19: Understanding greenlet

The Stacklet Sandwich (TM)

stacklet

continulet

greenlet

Page 20: Understanding 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

Page 21: Understanding greenlet

Using greenlet (II)main hub

g1 g2 g3 ...

Page 22: Understanding greenlet

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()

Page 23: Understanding greenlet

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!

Page 24: Understanding greenlet

Questions?

bettercallsaghul.com@saghul