def handle_request(req):
'''Process an incoming event.'''
unmarshall(req) # processing
validate(req) # processing
# some business logic # processing
record_event(req) # network i/o
update_db_counters(req) # network i/o
return_response()
work
work
work
wait
wait
Layers of Concurrency
Many machines EC2; Autoscale groups
Many processes Preforking web servers
Many threads Greenlets; asyncio
Containers ECS tasks
Serverless Lambdas
Reality def handle_request(req):
'''Process an incoming event.'''
unmarshall(req)
decrypt(req)
validate(req)
check_whether_duplicate(req) # BLOCKING i/o
# some business logic
# more business logic
# even more business logic
record_event(req) # nonblocking i/o
update_db_counters(req) # BLOCKING i/o
update_other_db_counters(req) # BLOCKING i/o
update_other_other_db_counters(req) # BLOCKING i/o
return_response()
Reality def handle_request(req):
'''Process an incoming event.'''
unmarshall(req)
decrypt(req)
validate(req)
check_whether_duplicate(req) # BLOCKING i/o
# some business logic
# more business logic
# even more business logic
record_event(req) # nonblocking i/o
update_db_counters(req) # BLOCKING i/o
update_other_db_counters(req) # BLOCKING i/o
update_other_other_db_counters(req) # BLOCKING i/o
return_response()
Reality def handle_request(req):
'''Process an incoming event.'''
unmarshall(req)
decrypt(req)
validate(req)
check_whether_duplicate(req) # BLOCKING i/o
# some business logic
# more business logic
# even more business logic
record_event(req) # nonblocking i/o
update_db_counters(req) # BLOCKING i/o
update_other_db_counters(req) # BLOCKING i/o
update_other_other_db_counters(req) # BLOCKING i/o
return_response()
Reality def handle_request(req):
'''Process an incoming event.'''
unmarshall(req)
decrypt(req)
validate(req)
check_whether_duplicate(req) # BLOCKING i/o
# some business logic
# more business logic
# even more business logic
record_event(req) # nonblocking i/o
update_db_counters(req) # BLOCKING i/o
update_other_db_counters(req) # BLOCKING i/o
update_other_other_db_counters(req) # BLOCKING i/o
return_response()
Redis client ✅ pure python
DynamoDB client ✅ pure python
Aerospike client ⛔ wrapped C code
Which DB Libraries Can Be Monkey Patched?
Too Much Processing? Yield Often.
def handle_request(req):
'''Process an incoming event.'''
unmarshall(req)
decrypt(req)
greenlet_yield()
validate(req)
check_whether_duplicate(req) # BLOCKING i/o
# some business logic
# more business logic
greenlet_yield()
# even more business logic
record_event(req) # nonblocking i/o
...
� Blocking I/O calls waste CPU
� You're not as I/O bound as you think hope
� C extensions play by different rules
● Blocking I/O calls waste CPU
■ Gevent + monkey patch
● You're not as I/O bound as you think hope
■ Buffer & batch
● C extensions play by different rules
■ Short timeouts w/retries