Slide 1

Slide 1 text

INTRODUCTION TO GEVENT a presentation by Isman Firmansyah

Slide 2

Slide 2 text

$ WHOAMI on Twitter @iromli on GitHub iromli http://groovematic.com/

Slide 3

Slide 3 text

WHAT IS GEVENT gevent is a -based Python networking library that uses to provide a high-level synchronous API on top of the event loop. coroutine greenlet libevent

Slide 4

Slide 4 text

GEVENT, UNDER THE HOOD http://gevent.org/

Slide 5

Slide 5 text

COROUTINE TL;DR http://en.wikipedia.org/wiki/Coroutine or in a nutshell: Well, a coroutine is a subroutine or function that can pause in the middle and return a value. When you call it again it picks up right where it was when you paused, environment intact, and keeps on going. http://is.gd/J2Zq0R

Slide 6

Slide 6 text

GREENLET http://greenlet.readthedocs.org/ A lightweight micro-thread.

Slide 7

Slide 7 text

LIBEVENT http://libevent.org/ A fast event loop; supports epoll, kqueue, select, etc.

Slide 8

Slide 8 text

WHEN TO USE GEVENT THE CONCLUSION (SO FAR) Use gevent for concurrent execution!!

Slide 9

Slide 9 text

CONCURRENCY DOES MATTER Concurrency is the composition of independently executing computations. It simulates the real-world. → Optimize performance and scalability. → http://is.gd/G0ewD8 http://is.gd/IsYrKF

Slide 10

Slide 10 text

FOR WEB DEVELOPERS: TACKLE THE C10K PROBLEM http://www.kegel.com/c10k.html Handle ten thousand clients simultaneously!!

Slide 11

Slide 11 text

CONCURRENCY IN PYTHON BATTERIES INCLUDED

Slide 12

Slide 12 text

THREADING GIL problems!! Might requires locking mechanism CPU-bound programs run significantly worse

Slide 13

Slide 13 text

MULTIPROCESSING Process-based "threading" Supports multi-cores Data passed between process must compatible with pickle

Slide 14

Slide 14 text

CONCURRENT.FUTURES Mimic of Java's concurrent.futures Available in Python 3.2+ Backport for Python 2.5 - 3.1 → https://pypi.python.org/pypi/futures

Slide 15

Slide 15 text

TULIP http://www.python.org/dev/peps/pep-3156/ Available in Python 3.4 ??

Slide 16

Slide 16 text

CONCURRENCY IN PYTHON 3RD-PARTY OPTIONS

Slide 17

Slide 17 text

TWISTED http://twistedmatrix.com/ OH: "Twisted is heavy, I agree but not bloated." uses Twisted as its core Graphite

Slide 18

Slide 18 text

TORNADO http://www.tornadoweb.org/ Battle-tested (originally developed at FriendFeed) Avoid libraries which doesn't compatible with Tornado's IOLoop

Slide 19

Slide 19 text

GEVENT ...

Slide 20

Slide 20 text

WHY NOT X - - - - - ... PyPy NodeJS Erlang Elixir Go Let's talk after this session ends :)

Slide 21

Slide 21 text

SERIOUSLY, WHY GEVENT ... AND WHY YOU SHOULD TRY IT

Slide 22

Slide 22 text

SYNCHRONOUS API Write program that looks blocking, but actually runs asynchronously. # blocking for x in xrange(1, 11): time.sleep() # non-blocking ops = [] for x in xrange(1, 11): ops.append(gevent.spawn(time.sleep)) gevent.joinall(ops)

Slide 23

Slide 23 text

NO CALLBACK-WORRIES Forget the callback!! def _collection_handler(self, callback=None, on_error=None): def inner(fd, ev): try: self._db.read_query_result() resultset = self._db.use_result() rows = self._get_rows(resultset) if callback: callback(rows) except Exception, exc: self._throw_error(exc, on_error) finally: self._ioloop.remove_handler(self._db.fd) return inner

Slide 24

Slide 24 text

MONKEY PATCHING UTILITY Patches stdlib and 3rd-party modules to become cooperative. import gevent.monkey gevent.monkey.patch_all() ops = [] for x in xrange(1, 11): ops.append(gevent.spawn(time.sleep)) gevent.joinall(ops) Caveats: cannot be used for C-extension

Slide 25

Slide 25 text

FAST SERVERS Based on libevent-http. wsgi.WSGIServer pyswgi.WSGIServer: supports SSL server.StreamServer: generic TCP server

Slide 26

Slide 26 text

HUGE COLLECTIONS OF COMPATIBLE LIBRARIES Thanks to monkey patching, we have abundant async libraries: MySQL => pymysql/ultramysql Redis => redis-py Beanstalk => beanstalkc Postgres => psycopg (with specific setup) ... and more

Slide 27

Slide 27 text

TOOLS BUILT ON TOP/SUPPORTS GEVENT / : load testing : Python implementation of the Socket.IO : Requests + Gevent : WSGI server ... and more locust.io boom gevent-socketio grequests gunicorn

Slide 28

Slide 28 text

GEVENT CRASH COURSE HOW TO ...??

Slide 29

Slide 29 text

SPAWNING GREENLET import gevent from gevent import Greenlet def foo(message, n): gevent.sleep(n) print message # Initialize a new Greenlet instance running the named function foo thread1 = Greenlet.spawn(foo, "Hello", 1) # Wrapper for Greenlet.spawn thread2 = gevent.spawn(foo, "I live!", 2) threads = [thread1, thread2] # Block until all threads complete. gevent.joinall(threads)

Slide 30

Slide 30 text

MONITORING GREENLET Use Greenlet states: started, ready, successful(), value, and exception. Mostly, you'll only need value and exception.

Slide 31

Slide 31 text

RETRIEVING THE VALUE FROM A GREENLET Use greenlet.value: import gevent def win(): return 'You win!' if __name__ == "__main__": winner = gevent.spawn(win) gevent.joinall([winner]) print "winner value:", winner.value # "You win!"

Slide 32

Slide 32 text

HANDLING EXCEPTION Use greenlet.exception: import gevent def fail(): raise Exception('You fail at failing.') if __name__ == "__main__": loser = gevent.spawn(fail) # Exceptions raised in the Greenlet, stay inside the Greenlet. try: gevent.joinall([loser]) except Exception as exc: print "This will never be reached!" # It is possible though to raise the exception again outside #raise loser.exception # Or using #loser.get() # A stack trace will be printed to stdout but it # will not unwind the stack of the parent. print "loser exception:", loser.exception

Slide 33

Slide 33 text

BONUS: THE HELLO WORLD OF CONCURRENT PROGRAMMING

Slide 34

Slide 34 text

WITHOUT GEVENT import time def boring(): print "without gevent" for x in xrange(1, 11): print "boring!", x time.sleep(1) if __name__ == "__main__": boring()

Slide 35

Slide 35 text

WITH GEVENT import gevent.monkey gevent.monkey.patch_all() import time def green(): print "with gevent" ops = [] for x in xrange(1, 11): print "boring!", x ops.append(gevent.spawn(time.sleep)) gevent.joinall(ops) if __name__ == "__main__": green()

Slide 36

Slide 36 text

MORE TUTORIALS http://sdiehl.github.io/gevent-tutorial/

Slide 37

Slide 37 text

QUESTIONS ANYONE?

Slide 38

Slide 38 text

THE END THANKS FOR LISTENING