The Many Faces of Concurrency in Python

Post on 13-Feb-2017

238 views 4 download

Transcript of The Many Faces of Concurrency in Python

Paradigms and tools for building high-performing systemsThe Many Faces of Concurrency in Python

Sagiv Malihismalihi@cisco.com @sagiv

2© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential

Who Am I?

3© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential

• Sagiv Malihi• SW Architect – SON Group• @sagiv• smalihi at cisco

4© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential

What are We Building?

5© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential

• Connect to all antennas to constantly make adjustments

• Read & analyze tons of statistics• Synchronize several physical

locations

Self Optimizing (cellular) Networks

6© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential

• Pelephone as 1st customer• followed by AT&T (!)• now already in tens of operators

the system had to grow

7© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential

We Needed to Scale!

8© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential

Concurrency vs.

Parallelism vs.

Distributed System

Concurrency – running multiple tasks in overlapping time

periods

Parallelism – when multiple tasks actually take place at

the same time (e.g. on separate cores)

Distributed Systems – execute tasks in parallel over

several machines (in different locations)

12© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential

Concurrency

Connecting to thousands of cell towers

Continuously tweaking tilt, coverage, handovers…

14© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential

• shared mem + switching = races• the GIL prevents true parallelism• threads are resource-intensive

threading is not a good choice

15© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential

• using threads is easy• IO is still concurrent• c extensions can release the GIL• IronPython / Jython are GIL-less

threading does have an upside

16© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential

• Predictable• Lightweight• Many libraries (incl. asyncio in stdlib)

coroutines to the rescue!

17© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential

def task1(): s = socket(...) while True: yield socket print socket.read()

def task2(): i = 1 while True: yield Sleep(1) print i i += 1

the basic idea is simpledef eventloop(*tasks): tasks = {task.next(): task for task in tasks} while True: sockets, sleeps =

filter_tasks(tasks) ready = select(sockets,

min(sleeps)) tasks = call_task_next(tasks,

ready)

eventloop(task1(), task2())

18© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential

import asyncioasync def slow_func(): await asyncio.sleep(1) return “answer”async def failed_func(): await asyncio.sleep(1) raise Exception(...)

python 3.5 async/await apiasync def test(): response = slow_func() try: await failed_func() except Exception as e:

print(e, await response)

loop = asyncio.get_event_loop()loop.run_until_complete(test())

19© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential

from gevent import monkey

monkey.patch_all()

gevent’s magic is a good tradeoff

20© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential

Parallelism

Hundreds of GB of binary logs & statistic files

are being parsed & processed every minute

22© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential

from multiprocessing import Process, Pipe

def f(conn): conn.send(“hello world”) conn.close()

multiprocessing is like magic!parent_conn, child_conn = Pipe()

p = Process(target=f, args=(child_conn,))

p.start()print(parent_conn.recv())

23© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential

• multiprocessing fork()’s• does not play well with gevent• or threads• or large datasets in memory• but fixed in python 3.4 !

magic is not always a good thing

24© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential

from slaveprocess // uses subprocess + RPyC import run_in_process

def f(): return (“hello world”)print (run_in_process(f))

using subprocess is easier

25© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential

Distributed Systems

Almost 200 servers

in 10 physical locations

working as a unified cluster

27© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential

• keeps a single-point-of-truth• on all servers• can act as a communications channel• we used mongodb

distributed DB can really help

28© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential

• locks generally lead to deadlocks • optimistic transaction model• nodes change the ‘network image’• verifying consistency before ‘commit’

try to avoid locking

29© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential

Summary

30© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential

• IO bound apps - • avoid threads, consider gevent• or asyncio

• CPU bound apps -• subprocess + RPyC

• distributed apps - • let a DB do the hard work

31© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential

Thank You!

Questions?