LAST UPDATE: July 17th 2018, 10:31:00 PM
John Reese - Thinking Outside the GIL with AsyncIO and Multiprocessing - PyCon 2018
给出了异步IO和多进程相结合的想法和实现
Multiprocessing
- Scales with CPU cores
- Automatic IPC
- Pool.map is really useful
多进程,每个进程有自己的GIL,可以避开限制实现真正的并发;
提供多种IPC渠道:Queue, Pipe…
自带接口非常nice,比如Pool.map
- One task per process
- Beware forking, pickling
每个进程实际上受到自己的GIL限制,只能运行一个任务
多进程处理时应注意内存复制导致内存占用过高问题
asyncio
- Based on futures
- Faster than threads
- Massive I/O concurrency
基于future -> 可以很好地和一些C++库配合使用
- Processing still limited by GIL
- Beware timeuts and queue length
asyncio是在单个进程的层面上,受到GIL的限制
如果异步队列过长,协程可能会在执行之前就超时
multiprocessing + asyncio
- Use multiprocessing primitives
- Event loop per process
- Queues for work/results
- Highly parallel workload
- Need to do some plumbing
每个进程运行独立的事件循环,把进程并发和异步IO结合起来
Optimizations
- Multiple work queues
- Combine tasks into batches
- Use spawned processes
multiprocessing.Queue内部有锁,单一时间内只能进行读或写,如果有多个子进程访问,可以分割数据后存储在多个队列
将多个任务组成一个批次传进进程
使用衍生进程,只继承必要的资源,相比fork和forkserver避免大量的内存占用,但启动速度更慢
Considerations
- Minimize what you pickle
- prechunk work items
- Aggregate results in the child
- Use map/reduce
减小pickle的规模,因为父子进程间消息传递需要pickle和unpickle
一些需要切成块状的数据可以预处理
子进程返回的数据可以适当进行合并
运用MapReduce
性能对比
https://raw.githubusercontent.com/jreese/aiomultiprocess/master/aiomultiprocess/core.py
引Nasy学姐说的一句:
多进程更多的原因是,单进程计算量不够,而异步则是因为一些 IO 或者 网络之类的拖慢了整体的速度。这样的一个任务是一个即是计算密集也是 IO 密集的(很奇怪)。
回过头来想想,好像是这么回事,有点强行的意思了
但是既然能把IO提高比单纯使用asyncio的8倍左右,似乎很nice很有进行实用的意义
(虽然对python web业内实际情况并没有很深的了解