Gevent what's the point

8,791 views
8,443 views

Published on

0 Comments
16 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
8,791
On SlideShare
0
From Embeds
0
Number of Embeds
234
Actions
Shares
0
Downloads
124
Comments
0
Likes
16
Embeds 0
No embeds

No notes for slide
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • 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

    ×