Slide 1

Slide 1 text

Non-Blocking Python By Tao Zhu

Slide 2

Slide 2 text

Tao Near 10 years exp as “full-stack” ! Lead Developer, Perform Group Plc

Slide 3

Slide 3 text

Repeated Stories
 PM: Why slow? System Admin: Seems only slow during peak hour? Developer: Seems only slow for login? DevOps: It is slow in the login process as there are many concurrent write ops into db and db starts lock row.

Slide 4

Slide 4 text

“DevOps” is killing Developers? Rise of “full-stack”? How to think like a “full-stack”?

Slide 5

Slide 5 text

Developing beyond big O Developer: I have implemented a binary- tree algo that is O(log n) System Admin: I have implemented B+ tree index that is better than O(log n) DevOps: 1. The single table is just too big. Time to break down into smaller tables? 2. Is your web server blocking

Slide 6

Slide 6 text

Blocking? What is that? A blocking web-server is similar to a phone call. ! You need to wait on-line to get a response and continue

Slide 7

Slide 7 text

A blocking server Django Server Process Django Server Process Django Server Process Django Server Process DB Django Server Process = context switching (via kernel) O(logn)

Slide 8

Slide 8 text

Non-blocking server Tornado Server Process DB = epoll (via kernel) O(1) Event loop

Slide 9

Slide 9 text

How to write Non-block server? Call Backs Coroutine (Decorator) Yield (Lazy Eval) def wait_for_messages(self, callback, cursor=None): if cursor: new_count = 0 for msg in reversed(self.cache): if msg["id"] == cursor: break new_count += 1 if new_count: callback(self.cache[-new_count:]) return self.waiters.add(callback) ! def cancel_wait(self, callback): self.waiters.remove(callback) ! class MessageNewHandler(BaseHandler): @tornado.web.authenticated @gen.coroutine def post(self): message = { "id": str(uuid.uuid4()), "from": self.current_user["first_name"], "body": self.get_argument("body"), } ! cursor = collection.find({'$or': [{'teamA': self.get_argument("body")},{'teamB' new_message = [self.get_argument("body"),"Matches:"] withMatch = False while (yield cursor.fetch_next): document = cursor.next_object() withMatch = True try: matchDatetime = document.get('data').get('prematch').get('match').get(' except: try: matchDatetime = document.get('data').get('match').get('start_time') except: pass ! print matchDatetime msg_str = matchDatetime+':'+document.get('teamA','')+' v '+ document.get('t if isinstance(document.get('goalA'), int ): msg_str = msg_str+' '+str(document.get('goalA',''))+' : '+ str(document new_message.append(msg_str) !

Slide 10

Slide 10 text

Non-blocking DB Driver Non-blocking through out the “Full Stack” PyMongo? No, it is blocking Use Motor

Slide 11

Slide 11 text

Demo - World Cup Genie

Slide 12

Slide 12 text

Take-aways How to think like a “Full-stack”? Look beyond coding and big(O) Blocking vs Non-Blocking Tornado Programming Essentials Callbacks,Coroutines, Yield Non-blocking Full Stack - Motor