代码之家  ›  专栏  ›  技术社区  ›  daveruinseverything

垃圾收集python子进程

  •  0
  • daveruinseverything  · 技术社区  · 6 年前

    tl;dr:我有一些返回值巨大的任务,它们会消耗大量内存。我要把它们交给一个 concurrent.futures.ProcessPoolExecutor . 子进程保留内存,直到它们接收到新任务。如何强制子进程有效地进行垃圾收集?

    实例

    import concurrent.futures
    import time
    
    executor = concurrent.futures.ProcessPoolExecutor(max_workers=1)
    
    def big_val():
        return [{1:1} for i in range(1, 1000000)]
    
    future = executor.submit(big_val)
    
    # do something with future result
    

    在上面的示例中,我在子流程中创建一个大对象,然后处理结果。从这一点开始,我可以处理父进程中的内存,但是由ProcessPoolExecutor创建的子进程将无限期地保留分配给我的任务的内存。

    我试过的

    def donothing():
        pass
    
    executor.submit(donothing)
    

    这是可行的,但a)相当笨拙,更重要的是b)不可信,因为我无法保证将任务发送到哪个子进程,所以唯一简单的方法是发送一个洪水,以确保我关心的子进程获得副本。

    据我所知,工作进程一旦完成运行我的任务,就没有理由保留结果。如果我的父进程为返回的 Future 将来

    我是误解了什么,还是这只是子进程如何引用内存的一个不幸的怪癖?如果是,是否有更好的解决办法?

    1 回复  |  直到 6 年前
        1
  •  2
  •   ShadowRanger    6 年前

    问题是,工作进程 binds the result to a local name r before sending it back to the parent ,并且只替换 当新任务到来时。

    the CPython bug tracker del r 打完电话 _sendback_result ; 它已经这样做了 call_item (打包后的函数和发送给工作者的参数)出于完全相同的原因,以避免在资源的可用窗口之外保留资源,并且对已经返回且不再相关的结果执行相同的操作是有意义的。