Python 多处理内存泄漏,永久存在的进程
我试图解决一个多处理内存泄漏问题,并试图完全理解问题所在。我的体系结构正在寻找以下内容:将任务委托给几个子流程的主流程。目前只有3个子流程。我使用队列将数据发送到这些子进程,除了内存泄漏之外,它工作正常 似乎大多数人要么忘记了加入/退出/结束他们的流程,要么在完成后忘记了。我的情况有点不同。我希望这些过程在应用程序的整个过程中永远存在。因此,主进程将启动这3个子进程,直到整个应用程序消亡,它们才会消亡 我还需要加入他们吗 这是一个永远保留流程的坏主意吗?我是否应该考虑杀死他们,并重新启动他们在某个点,尽管我不想这样做? 我不应该在这个用例中使用multiprocessing.Process吗 我在子进程中进行了大量API调用,生成了大量字典和数据数组。我假设我的内存泄漏是因为没有正确清理它。也许我的问题完全在那里,与我使用多重处理的方式无关Python 多处理内存泄漏,永久存在的进程,python,python-3.x,memory-leaks,multiprocessing,Python,Python 3.x,Memory Leaks,Multiprocessing,我试图解决一个多处理内存泄漏问题,并试图完全理解问题所在。我的体系结构正在寻找以下内容:将任务委托给几个子流程的主流程。目前只有3个子流程。我使用队列将数据发送到这些子进程,除了内存泄漏之外,它工作正常 似乎大多数人要么忘记了加入/退出/结束他们的流程,要么在完成后忘记了。我的情况有点不同。我希望这些过程在应用程序的整个过程中永远存在。因此,主进程将启动这3个子进程,直到整个应用程序消亡,它们才会消亡 我还需要加入他们吗 这是一个永远保留流程的坏主意吗?我是否应该考虑杀死他们,并重新启动他们在某
from multiprocessing import Process
# This is how I'm creating my 3 sub processes
procs = []
for name in names:
proc = Process(target=print_func, args=(name,))
procs.append(proc)
proc.start()
# Then I want my sub-processes to live forever for the remainder of the application's life
# But memory leaks until I run out of memory
更新1:
ubuntu:~/Folder/$ free -m
total used free shared buff/cache available
Mem: 7610 3920 2901 0 788 3438
Swap: 0 0 0
ubuntu:~/Folder/$ free -m
total used free shared buff/cache available
Mem: 7610 7385 130 0 93 40
Swap: 0 0 0
ubuntu:~/Folder/$
- 我在MacOS 10.15.5和Ubuntu 16.04上看到了内存的增长/泄漏。它在两个OSs中的行为方式相同。我尝试了Python3.6和Python3.8,并看到了相同的结果
- 在进行多进程处理之前,我从未发生过这种泄漏。这就是为什么我认为这与多进程有关。所以当我在一个进程上运行代码时->没有泄漏。有一次我使用多进程运行相同的代码->内存泄漏/膨胀
- 实际膨胀的数据是数据列表(浮动和字符串)。我使用python包确认了这一点,它是一个内存分析器
- 自从添加多进程特性以来,最大的变化是,我的数据在子进程中收集,然后使用发送到主进程。所以我想知道是否有新的指针以某种方式阻止python进行垃圾收集并完全释放这些浮点数和字符串列表
- 我有一个功能,每隔30秒清除我不再需要的“旧”数据(因为我的数据是时间敏感的)。我目前正在调查这件事,看看它是否如预期的那样工作
ubuntu:~/Folder/$ free -m
total used free shared buff/cache available
Mem: 7610 3920 2901 0 788 3438
Swap: 0 0 0
ubuntu:~/Folder/$ free -m
total used free shared buff/cache available
Mem: 7610 7385 130 0 93 40
Swap: 0 0 0
ubuntu:~/Folder/$
我改进了删除旧目录和列表的方式。这似乎有所帮助,但问题仍然存在。python包pympler表明我不再泄漏内存了,这很好。当我在mac上运行它时,我的活动监视器显示内存使用量持续增加。当我在Ubuntu上运行它时,free-m命令也显示出一致的内存膨胀
以下是运行脚本后不久我的内存情况:
ubuntu:~/Folder/$ free -m
total used free shared buff/cache available
Mem: 7610 3920 2901 0 788 3438
Swap: 0 0 0
ubuntu:~/Folder/$ free -m
total used free shared buff/cache available
Mem: 7610 7385 130 0 93 40
Swap: 0 0 0
ubuntu:~/Folder/$
运行一段时间后,内存会根据空闲时间膨胀-m:
ubuntu:~/Folder/$ free -m
total used free shared buff/cache available
Mem: 7610 3920 2901 0 788 3438
Swap: 0 0 0
ubuntu:~/Folder/$ free -m
total used free shared buff/cache available
Mem: 7610 7385 130 0 93 40
Swap: 0 0 0
ubuntu:~/Folder/$
它最终由于使用太多内存而崩溃
为了测试泄漏的来源,我关闭了子进程通过Pyzmq向主进程发送数据的功能。因此,子流程仍然在进行API调用和收集数据,只是没有对其进行任何处理。当我这样做时,内存泄漏完全消失了。显然,从子进程发送数据,然后在主进程上处理数据的过程就是泄漏发生的地方。我将继续调试
更新3可能已解决:
ubuntu:~/Folder/$ free -m
total used free shared buff/cache available
Mem: 7610 3920 2901 0 788 3438
Swap: 0 0 0
ubuntu:~/Folder/$ free -m
total used free shared buff/cache available
Mem: 7610 7385 130 0 93 40
Swap: 0 0 0
ubuntu:~/Folder/$
我可能已经解决了这个问题。仍在进行更彻底的测试。我在包含数据的dict和列表上做了一些额外的内存清理。我还为我的EC2实例提供了大约20GB的内存。我的应用程序内存使用时间线如下所示:
1分钟后的运行时间:~4 GB
2分钟后的运行时间:~5 GB
3分钟后的运行时间:~6 GB
5分钟后的运行时间:~7 GB
10分钟后的运行时间:~9 GB
6小时后的运行时间:~9 GB
10小时后的运行时间:~9 GB
奇怪的是这种缓慢的增长。基于我的代码是如何工作的,我不明白它是如何慢慢地将内存使用从第2分钟增加到第10分钟的。它应该在大约2或3分钟内使用最大内存。另外,以前,当我在一个进程上运行所有这些逻辑时,我的内存使用率非常低。我不记得它到底是什么,但它比9GB低很多
我在Pyzmq上读了一些书,它似乎占用了大量内存。我认为大量内存使用的增加来自Pyzmq。因为我用它在进程之间发送大量数据。我读到Pyzmq从大数据消息中释放内存的速度非常慢所以很有可能我的内存泄漏不是真正的内存泄漏,只是由于Pyzmq和多处理发送数据,我使用了更多的内存。。我可以通过在一台内存约为20GB的机器上运行最近更改之前的代码来确认这一点
更新4已解决:
ubuntu:~/Folder/$ free -m
total used free shared buff/cache available
Mem: 7610 3920 2901 0 788 3438
Swap: 0 0 0
ubuntu:~/Folder/$ free -m
total used free shared buff/cache available
Mem: 7610 7385 130 0 93 40
Swap: 0 0 0
ubuntu:~/Folder/$
我以前的理论是正确的。从一开始就没有内存泄漏。Pyzmq与大量数据的结合使用极大地增加了内存使用量,以至于我必须在EC2实例上使用大约6倍的内存。因此Pyzmq似乎要么使用大量内存,要么在释放内存方面非常缓慢,要么两者兼而有之。不管怎样,这个问题已经解决了。考虑到您使用的是Linux,我建议您使用来理解进程增长的原因 为此,首先使用ps计算每个进程(主进程和子进程)的进程ID,然后为每个进程使用“gcore”来收集活动核心。在每一个进程的核心增长一点后,再次收集它们 对于每个core,您可以在chap中打开它并使用以下命令:
redirect on
describe used
结果将是名为