• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Gevent what's the point
 

Gevent what's the point

on

  • 6,639 views

 

Statistics

Views

Total Views
6,639
Views on SlideShare
6,399
Embed Views
240

Actions

Likes
10
Downloads
85
Comments
0

6 Embeds 240

http://join5works.com 187
http://5works.co 25
https://twitter.com 17
https://twimg0-a.akamaihd.net 5
https://si0.twimg.com 3
http://ec2-122-248-224-251.ap-southeast-1.compute.amazonaws.com 3

Accessibility

Upload Details

Uploaded via as Apple Keynote

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • \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 Gevent what's the point Presentation Transcript

  • 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(): x = db.query(...) x.addCallback(_db_cb)
  • 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): tokenizer.send(c) r += sock.recv(4096)
  • 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)
  • 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 World!if __name__ == __main__: app.run()
  • 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()
  • from flask import Flaskapp = Flask(__name__)@app.route(/)def hello_world(): import time; time.sleep(1) return Hello World!if __name__ == __main__: app.run()
  • from flask import Flaskapp = Flask(__name__)
  • 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()
  • 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 callback socket 1, socket 2, ... kernel write buffer 1 read buffer 1 write buffer 2 read buffer 2
  • 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] = 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])))
  • 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])
  • Part III: SocketsSocketsWhat magic lies here
  • 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)
  • 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)
  • 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)
  • 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 Initialized Python Initial Stack
  • Green Thread Execution Green ThreadGreen StackThread Stack Gevent Initialized Python Initial Stack
  • Green Thread Execution Green Green Thread ThreadGreen Stack StackThread Stack Gevent Initialized Python Initial Stack
  • Green Thread Execution Green Green Thread ThreadGreen Stack StackThread Stack Gevent Initialized Python Initial Stack
  • Green Thread Execution Green Green Thread ThreadGreen Stack StackThread Stack Gevent Initialized Python Initial Stack
  • 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;
  • 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