The Many Faces of Concurrency in Python
Sagiv Malihi
Paradigms and tools for building high-performing systems
@sagiv
1
© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential
Who Am I?
2
© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential
2
© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential
3
© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential
What are We Building?
4
© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential
4
© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential
Self Optimizing (cellular) Networks
5
© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential
the system had to grow
6
© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential
We Needed to Scale!
7
© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential
7
© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential
Concurrency
vs.
Parallelism
vs.
Distributed System
8
© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential
Concurrency – running multiple tasks in overlapping time periods
9
© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential
Parallelism – when multiple tasks actually take place at the same time (e.g. on separate cores)
10
© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential
Distributed Systems – execute tasks in parallel over several machines (in different locations)
11
© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential
Concurrency
12
© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential
12
© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential
Connecting to thousands of cell towers
Continuously tweaking tilt, coverage, handovers…
13
© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential
threading is not a good choice
14
© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential
threading does have an upside
15
© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential
coroutines to the rescue!
16
© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential
the basic idea is simple
def task1():
s = socket(...)
while True:
yield socket
print socket.read()
def task2():
i = 1
while True:
yield Sleep(1)
print i
i += 1
def 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())
17
© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential
python 3.5 async/await api
import asyncio
async def slow_func():
await asyncio.sleep(1)
return “answer”
async def failed_func():
await asyncio.sleep(1)
raise Exception(...)
async 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())
18
© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential
gevent’s magic is a good tradeoff
from gevent import monkey monkey.patch_all()
19
© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential
Parallelism
20
© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential
20
© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential
Hundreds of GB of binary logs & statistic files
are being parsed & processed every minute
21
© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential
multiprocessing is like magic!
from multiprocessing import
Process, Pipe
def f(conn):
conn.send(“hello world”)
conn.close()
parent_conn, child_conn = Pipe()
p = Process(target=f,
args=(child_conn,))
p.start()
print(parent_conn.recv())
22
© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential
magic is not always a good thing
23
© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential
using subprocess is easier
from slaveprocess // uses subprocess + RPyC
import run_in_process
def f():
return (“hello world”)
print (run_in_process(f))
24
© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential
Distributed Systems
25
© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential
25
© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential
Almost 200 servers
in 10 physical locations
working as a unified cluster
26
© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential
distributed DB can really help
27
© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential
try to avoid locking
28
© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential
Summary
29
© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential
29
© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential
30
© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential
Thank You!
Questions?
31
© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential
31
© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential
32
© 2014 Cisco and/or its affiliates. All rights reserved. Cisco Confidential