简体   繁体   English

多重处理:分叉的缺点?

[英]Multiprocessing: Downsides of Forking?

We are experiencing an issue with Python Celery (which uses multiprocessing) where large periodic (scheduled) tasks consume massive amounts of memory for short bursts of time, but because the worker process lives through the life of the pool ( MAX_TASKS_PER_CHILD=None ), the memory is not garbage collected (ie. it is being "high-water" reserved). 我们遇到了Python Celery(使用多处理)的问题,其中大型定期任务(计划任务)在短时间突发内消耗大量内存,但是由于工作进程在池的整个生命周期中都存在( MAX_TASKS_PER_CHILD=None ),因此内存不是垃圾收集的(即,它是“高水位”保留的)。

(This problem is further worsened by Heroku, which sees a large, constant amount of memory allocated and turns it into swap, which decreases performance.) (Heroku进一步恶化了这个问题,它看到分配了一个大而恒定的内存并将其转换为swap,从而降低了性能。)

We have found that by setting MAX_TASKS_PER_CHILD=1 , we fork a new process (Celery worker instance) after every task, and memory is properly garbage collected. 我们发现通过设置MAX_TASKS_PER_CHILD=1 ,我们在每个任务之后派生一个新进程(Celery worker实例),并且可以正确地回收内存。 Sweet! 甜!

However, there are plenty of articles that suggest the same solution, but I have not identified any downsides. 但是,有很多文章提出了相同的解决方案,但是我没有发现任何缺点。 What are the potential downsides of forking a new process after every task? 在完成每项任务之后创建新流程的潜在弊端是什么?

My guesses would be: 我的猜测是:
1. CPU overhead (but probably a tiny amount) 1. CPU开销(但可能很小
2. Potential errors when forking (but I can't find any documentation on this) 2.分叉时的潜在错误(但我找不到与此相关的任何文档)

Aside from the obvious increase in CPU overhead from repeated forking (not a big deal if the workers do enough work per task), one possible downside would be if the parent process continues to grow in size. 除了重复分叉会明显增加CPU开销(如果工人完成每个任务足够大的工作量,这没什么大不了的),还有一个可能的缺点是,如果父进程的大小继续增长。 If so, it increases the size of all the child processes (which are forking a larger and larger parent). 如果是这样,它将增加所有子进程的大小(它们正在分叉越来越大的父进程)。 This wouldn't matter so much (presumably little of the memory will be written, and therefore little copying is required and actual memory use won't be a major issue), but IIRC, the Linux overcommit heuristics assume that the COW memory will eventually be copied, and you could invoke the OOM killer even if you're nowhere near actually exceeding the heuristic limit in terms of private pages. 这无关紧要(大概将只写很少的内存,因此几乎不需要复制,实际的内存使用也不会成为主要问题),但是IIRC,Linux过度使用启发式算法假设COW内存最终会被复制,即使您实际上还没有超出私有页面方面的启发式限制,您也可以调用OOM杀手。

On Python 3.4 and higher, you can avoid this issue by explicitly setting your multiprocessing start method to forkserver on program launch (before doing any work the workers don't rely on), which will fork workers from a separate server process that should not dramatically increase in size. 在Python 3.4及更高版本上,您可以通过在程序启动时显式地将您的multiprocessing启动方法设置为forkserver来避免此问题(在执行工作者不依赖的任何工作之前),这将使工人从单独的服务器进程中分叉,该服务器进程不应显着尺寸增加。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM