Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
GeventWhat’s the point?       Sean McQuillan    sean@bittorrent.com
Bottom LineGevent is fast (libev)Pythonic styleSingle threaded event loop
Gevent is Fast        application code            geventlibev                  greenlet            kernel
Pythonic Styledef get_db():    return db.query(...)            vsdef _db_cb(result):    consumer.send(result)def get_db():...
Single Threaded     Event LoopSingle threaded
Single Threaded     Event LoopSingle threaded wait
Single Threaded     Event LoopSingle threaded wait what?
Execution ModelOne OS threadOnly ONE thing happens at a time... Switching constantly
More Execution Modeldef example_function(sock):    r = sock.recv(4096)    count = len(r)    for c in xrange(count):       ...
More Execution Modeldef example_function(sock):    r = sock.recv(4096)    count = len(r)    for c in xrange(count):       ...
More Execution Model def get_db():     return db.query(...)
More Execution Model def get_db():     return db.query(...)
Basic Example
from flask import Flaskapp = Flask(__name__)@app.route(/)def hello_world():    import time; time.sleep(1)    return Hello ...
from flask import Flaskapp = Flask(__name__)import gevent.monkeygevent.monkey.patch_all()@app.route(/)def hello_world():  ...
from flask import Flaskapp = Flask(__name__)@app.route(/)def hello_world():    import time; time.sleep(1)    return Hello ...
from flask import Flaskapp = Flask(__name__)
from flask import Flaskapp = Flask(__name__)import gevent.monkeygevent.monkey.patch_all()@app.route(/)def hello_world():  ...
from flask import Flaskapp = Flask(__name__)import gevent.monkeygevent.monkey.patch_all()
Interlude:Monkey Patching
Monkey PatchingReplace existing librariesNot generally done in python
Monkey Patchingsys.modules[socket] = gevent.socketsys.modules[time] = gevent.sleep...
Part II: Event LoopsLow overheadSingle threadedHandle LOTS of connections
poll, select, epoll, kqueue “Given a list of file descriptors which are ready for read or write.”
Lets dig in        application code            geventlibev                  greenlet            kernel
Lets dig insocket 1 write callback   event      socket 1 read callbacksocket 2 write callback    loop      socket 2 read c...
ExampleContrived event loop exampleSee t wisted event loop for real examplet wisted/interent/selectreactor.py
Examplerlist = []wlist = []callbacks = {}pending = defaultdict(str)def want_to_read(sock, cb):    callbacks[sock.fileno] =...
Exampledef event_loop():    while True:        reads, writes, _ = select(rlist, wlist, [])        for readfd in reads:    ...
Part III: SocketsSocketsWhat magic lies here
patched socket.recvdef recv(self, *args):    sock = self._sock    while True:        try:             return sock.recv(*ar...
patched socket.recvdef recv(self, *args):    sock = self._sock    while True:        try:             return sock.recv(*ar...
patched socket.recvdef recv(self, *args):    sock = self._sock    while True:        try:             return sock.recv(*ar...
Part IV: Greenlets“green” threads
Part IV: Greenlets“green” threads(that means fake threads)
Part IV: Greenlets“green” threads(that means fake threads)
Green Threads GoodNever switch accidentallyNever spend time blocked on IOHigh performance switching
Green Threads BadNever preemptively interruptNo SMP
Green Thread Execution     Python Initial Stack
Green Thread Execution      Gevent Initialized     Python Initial Stack
Green Thread ExecutionGreenThread Stack          Gevent Initialized         Python Initial Stack
Green Thread Execution               Green               ThreadGreen           StackThread Stack          Gevent Initializ...
Green Thread Execution                Green                ThreadGreen            StackThread Stack          Gevent Initia...
Green Thread Execution                Green Green                Thread ThreadGreen            Stack StackThread Stack    ...
Green Thread Execution                Green     Green                Thread    ThreadGreen            Stack     StackThrea...
Green Thread Execution                Green     Green                Thread    ThreadGreen            Stack     StackThrea...
How does it switch?  (x86 assembly)    void *ebp, *ebx;    unsigned short cw;    register int *stackref, stsizediff;    __...
When to use GeventReplace thread-based ser versReplace thread-based clientsLighter than multiprocessing
When not to use gevent When SMP is required High CPU load Latency guarntees Memory star ved systems
TwistedMature, async-baked, implementationsof most protocols DNS Ser ver SSH Server AWS AMQP Web
TornadoHTTPHighly performantLess protocol / library support                            I’m not an expert
ErlangScales more vertically (dozens of cores)Similar execution modelLess library support
Python ThreadingI’ve never tried to write a “web-scale”server with it, would love to hear yourexperience
Python  MultiproccessingGreat SMP usage
GoNever used, benchmarks look good
The End
Gevent what's the point
Gevent what's the point
Gevent what's the point
Gevent what's the point
Upcoming SlideShare
Loading in …5
×

Gevent what's the point

9,158 views

Published on

  • Be the first to comment

Gevent what's the point

  1. 1. GeventWhat’s the point? Sean McQuillan sean@bittorrent.com
  2. 2. Bottom LineGevent is fast (libev)Pythonic styleSingle threaded event loop
  3. 3. Gevent is Fast application code geventlibev greenlet kernel
  4. 4. Pythonic Styledef get_db(): return db.query(...) vsdef _db_cb(result): consumer.send(result)def get_db(): x = db.query(...) x.addCallback(_db_cb)
  5. 5. Single Threaded Event LoopSingle threaded
  6. 6. Single Threaded Event LoopSingle threaded wait
  7. 7. Single Threaded Event LoopSingle threaded wait what?
  8. 8. Execution ModelOne OS threadOnly ONE thing happens at a time... Switching constantly
  9. 9. More Execution Modeldef example_function(sock): r = sock.recv(4096) count = len(r) for c in xrange(count): tokenizer.send(c) r += sock.recv(4096)
  10. 10. More Execution Modeldef example_function(sock): r = sock.recv(4096) count = len(r) for c in xrange(count): tokenizer.send(c) r += sock.recv(4096)
  11. 11. More Execution Model def get_db(): return db.query(...)
  12. 12. More Execution Model def get_db(): return db.query(...)
  13. 13. Basic Example
  14. 14. from flask import Flaskapp = Flask(__name__)@app.route(/)def hello_world(): import time; time.sleep(1) return Hello World!if __name__ == __main__: app.run()
  15. 15. from flask import Flaskapp = Flask(__name__)import gevent.monkeygevent.monkey.patch_all()@app.route(/)def hello_world(): import time; time.sleep(1) return Hello World!if __name__ == __main__: app.run()
  16. 16. from flask import Flaskapp = Flask(__name__)@app.route(/)def hello_world(): import time; time.sleep(1) return Hello World!if __name__ == __main__: app.run()
  17. 17. from flask import Flaskapp = Flask(__name__)
  18. 18. from flask import Flaskapp = Flask(__name__)import gevent.monkeygevent.monkey.patch_all()@app.route(/)def hello_world(): import time; time.sleep(1) return Hello World!if __name__ == __main__: app.run()
  19. 19. from flask import Flaskapp = Flask(__name__)import gevent.monkeygevent.monkey.patch_all()
  20. 20. Interlude:Monkey Patching
  21. 21. Monkey PatchingReplace existing librariesNot generally done in python
  22. 22. Monkey Patchingsys.modules[socket] = gevent.socketsys.modules[time] = gevent.sleep...
  23. 23. Part II: Event LoopsLow overheadSingle threadedHandle LOTS of connections
  24. 24. poll, select, epoll, kqueue “Given a list of file descriptors which are ready for read or write.”
  25. 25. Lets dig in application code geventlibev greenlet kernel
  26. 26. Lets dig insocket 1 write callback event socket 1 read callbacksocket 2 write callback loop socket 2 read callback socket 1, socket 2, ... kernel write buffer 1 read buffer 1 write buffer 2 read buffer 2
  27. 27. ExampleContrived event loop exampleSee t wisted event loop for real examplet wisted/interent/selectreactor.py
  28. 28. Examplerlist = []wlist = []callbacks = {}pending = defaultdict(str)def want_to_read(sock, cb): callbacks[sock.fileno] = cb global rlist rlist = list(set(rlist + [sock.fileno]))def want_to_write(sock, data): pending[sock.fileno] += data global wlist wlist = list(set(wlist + [sock.fileno])))
  29. 29. Exampledef event_loop(): while True: reads, writes, _ = select(rlist, wlist, []) for readfd in reads: data = _do_actual_read(readfd) callbacks[readfd](data) for writefd in writes: _do_actual_write(pending[writefd])
  30. 30. Part III: SocketsSocketsWhat magic lies here
  31. 31. patched socket.recvdef recv(self, *args): sock = self._sock while True: try: return sock.recv(*args) except error: ex = sys.exc_info()[1] if ex.args[0] == EBADF: return if (ex.args[0] != EWOULDBLOCK or self.timeout == 0.0 ): raise self._wait(self._read_event)
  32. 32. patched socket.recvdef recv(self, *args): sock = self._sock while True: try: return sock.recv(*args) except error: ex = sys.exc_info()[1] if ex.args[0] == EBADF: return if (ex.args[0] != EWOULDBLOCK or self.timeout == 0.0 ): raise self._wait(self._read_event)
  33. 33. patched socket.recvdef recv(self, *args): sock = self._sock while True: try: return sock.recv(*args) except error: ex = sys.exc_info()[1] if ex.args[0] == EBADF: return if (ex.args[0] != EWOULDBLOCK or self.timeout == 0.0 ): raise self.want_to_read(sock, self.mygreenthread.switch)
  34. 34. Part IV: Greenlets“green” threads
  35. 35. Part IV: Greenlets“green” threads(that means fake threads)
  36. 36. Part IV: Greenlets“green” threads(that means fake threads)
  37. 37. Green Threads GoodNever switch accidentallyNever spend time blocked on IOHigh performance switching
  38. 38. Green Threads BadNever preemptively interruptNo SMP
  39. 39. Green Thread Execution Python Initial Stack
  40. 40. Green Thread Execution Gevent Initialized Python Initial Stack
  41. 41. Green Thread ExecutionGreenThread Stack Gevent Initialized Python Initial Stack
  42. 42. Green Thread Execution Green ThreadGreen StackThread Stack Gevent Initialized Python Initial Stack
  43. 43. Green Thread Execution Green ThreadGreen StackThread Stack Gevent Initialized Python Initial Stack
  44. 44. Green Thread Execution Green Green Thread ThreadGreen Stack StackThread Stack Gevent Initialized Python Initial Stack
  45. 45. Green Thread Execution Green Green Thread ThreadGreen Stack StackThread Stack Gevent Initialized Python Initial Stack
  46. 46. Green Thread Execution Green Green Thread ThreadGreen Stack StackThread Stack Gevent Initialized Python Initial Stack
  47. 47. How does it switch? (x86 assembly)    void *ebp, *ebx;    unsigned short cw;    register int *stackref, stsizediff;    __asm__ volatile ("" : : : "esi", "edi");    __asm__ volatile ("fstcw %0" : "=m" (cw));    __asm__ volatile ("movl %%ebp, %0" : "=m" (ebp));    __asm__ volatile ("movl %%ebx, %0" : "=m" (ebx));    __asm__ ("movl %%esp, %0" : "=g" (stackref));    {        SLP_SAVE_STATE(stackref, stsizediff);        __asm__ volatile (            "addl %0, %%espn"            "addl %0, %%ebpn"            :            : "r" (stsizediff)            );        SLP_RESTORE_STATE();    }    __asm__ volatile ("movl %0, %%ebx" : : "m" (ebx));    __asm__ volatile ("movl %0, %%ebp" : : "m" (ebp));    __asm__ volatile ("fldcw %0" : : "m" (cw));    __asm__ volatile ("" : : : "esi", "edi");    return 0;
  48. 48. When to use GeventReplace thread-based ser versReplace thread-based clientsLighter than multiprocessing
  49. 49. When not to use gevent When SMP is required High CPU load Latency guarntees Memory star ved systems
  50. 50. TwistedMature, async-baked, implementationsof most protocols DNS Ser ver SSH Server AWS AMQP Web
  51. 51. TornadoHTTPHighly performantLess protocol / library support I’m not an expert
  52. 52. ErlangScales more vertically (dozens of cores)Similar execution modelLess library support
  53. 53. Python ThreadingI’ve never tried to write a “web-scale”server with it, would love to hear yourexperience
  54. 54. Python MultiproccessingGreat SMP usage
  55. 55. GoNever used, benchmarks look good
  56. 56. The End

×