我有一个使用subprocess.Popen()
运行和管理许多服务的应用程序。这些服务中的每一个都会一直运行,直到明确告知它为止。我注意到,从subprocess.Popen()
调用返回的时间以相当线性的速率增加,因为仲裁器生成了更多进程。
我的基本代码如下:
process_list = []
for command in command_list:
start_tm = time.time()
process = subprocess.Popen(cmd,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
end_tm = time.time()
print end_tm-start_tm
process_list.append(process)
我发现随着我产生越来越多的进程,end_tm-start_tm
的打印量会增加。每个command
运行的服务可以按任何顺序排列,我看到相同的行为。时间增加不是完全线性的,但我一直看到一个模式:第一个过程需要~0.005秒产生,第10个需要~0.125秒,第20个过程需要~0.35秒,依此类推。
我的仲裁进程运行了超过100个子进程。我可以拆分它,以便多个仲裁器运行时每个子进程数量较少,但我想先了解问题所在。一个进程的开销是否拥有许多子进程,以至于每个额外的子进程都会增加subprocess.Popen()
的返回时间?我有什么办法可以减轻这种影响吗?
在这两种情况下,第一个过程再次需要约0.005秒启动,第32个和最后一个过程需要约0.45秒才能启动。在我之前对64个进程的单个仲裁器的测试中,第一个进程需要约0.005秒才能启动,而第64个进程需要大约0.85秒。
答案 0 :(得分:0)
不直接回答您关于“为什么”您正在注意到的问题,但我强烈建议您使用ThreadPoolExecutor
管理系统资源来更改处理多处理的策略。
由于您的系统无法有效管理比系统线程更多的进程,我会尝试:
>>> from concurrent.futures import ThreadPoolExecutor
>>> from multiprocessing import cpu_count
>>> with ThreadPoolExecutor(workers=cpu_count()) as pool:
results = pool.map(lambda cmd: subprocess.Popen(cmd,stdout=subprocess.PIPE,stderr=subprocess.PIPE), command_list)
我发现API很容易,资源管理非常有效,而且“陷阱”更少。
虽然这是针对3.6的,但一旦pip install
concurrent.futures
模块为2.7,API就大致相同。