amo*_*mos 5 python garbage-collection multiprocessing python-2.7 psutil
我有类似于此的代码:
def memoryIntensiveFunction(x):
largeTempVariable = Intermediate(x)
processFunction(largeTempVariable,x)
Run Code Online (Sandbox Code Playgroud)
问题在于,temp在我的测试用例中,该变量类似于 500 mb,但该空间在memoryIntensiveFunction完成后不会返回给操作系统。我知道这是因为使用该guppy工具进行的内存分析说largeTempVariable已释放(即,在 Python 中),但psutil表明它不是。我想我看到了这里描述的效果。问题是这个过程运行时间很长(即几个小时),memoryIntensiveFunction在开始时运行并且永远不会再次运行,所以我不得不携带 500mb 几个小时很不方便。
我在这里和这里找到的一个解决方案建议使用单独的过程。多处理会产生自己的成本,但就我而言,这是值得的。但是,这需要重构memoryIntensiveFunction调用者以接收x返回值,而不是看到它就地修改。真正的杀手是我的对象x不可选择(它大量使用了 boost python 扩展)。使可x腌制的工作量很大。
有没有我没有考虑的选项?
这看起来很奇怪,我试图重现你的问题,并且似乎简单的“del”就足够了。为了进行演示,您可以运行以下代码:
import itertools
import pdb
def test():
a = "a"
for _ in itertools.repeat(None, 30):
a += a
pdb.set_trace()
del a
pdb.set_trace()
test()
Run Code Online (Sandbox Code Playgroud)
在第一个断点处,您将看到它使用大约 1GB 的 ram(您需要 python3.3 条目):
Private + Shared = RAM used Program
4.0 KiB + 9.0 KiB = 13.0 KiB VisualGDB-DisownTTY-r1
4.0 KiB + 15.0 KiB = 19.0 KiB sharing-tests
4.0 KiB + 19.5 KiB = 23.5 KiB dhcpcd
4.0 KiB + 31.5 KiB = 35.5 KiB gdb
4.0 KiB + 36.0 KiB = 40.0 KiB vim [deleted]
4.0 KiB + 38.0 KiB = 42.0 KiB systemd-udevd
40.0 KiB + 10.0 KiB = 50.0 KiB init
24.0 KiB + 135.0 KiB = 159.0 KiB agetty (6)
12.0 KiB + 150.0 KiB = 162.0 KiB su (3)
88.0 KiB + 103.0 KiB = 191.0 KiB syslog-ng (2)
152.0 KiB + 55.0 KiB = 207.0 KiB crond
172.0 KiB + 81.0 KiB = 253.0 KiB python3.4
580.0 KiB + 220.5 KiB = 800.5 KiB sshd (3)
768.0 KiB + 932.0 KiB = 1.7 MiB bash (13)
2.8 MiB + 118.0 KiB = 2.9 MiB mongod
7.4 MiB + 109.0 KiB = 7.5 MiB tmux [deleted] (2)
1.0 GiB + 1.2 MiB = 1.0 GiB python3.3
---------------------------------
1.0 GiB
=================================
Run Code Online (Sandbox Code Playgroud)
然后在第二个断点处,删除变量后,内存被释放:
Private + Shared = RAM used Program
4.0 KiB + 9.0 KiB = 13.0 KiB VisualGDB-DisownTTY-r1
4.0 KiB + 15.0 KiB = 19.0 KiB sharing-tests
4.0 KiB + 19.5 KiB = 23.5 KiB dhcpcd
4.0 KiB + 31.5 KiB = 35.5 KiB gdb
4.0 KiB + 36.0 KiB = 40.0 KiB vim [deleted]
4.0 KiB + 38.0 KiB = 42.0 KiB systemd-udevd
40.0 KiB + 10.0 KiB = 50.0 KiB init
24.0 KiB + 135.0 KiB = 159.0 KiB agetty (6)
12.0 KiB + 150.0 KiB = 162.0 KiB su (3)
88.0 KiB + 103.0 KiB = 191.0 KiB syslog-ng (2)
152.0 KiB + 55.0 KiB = 207.0 KiB crond
172.0 KiB + 81.0 KiB = 253.0 KiB python3.4
584.0 KiB + 220.5 KiB = 804.5 KiB sshd (3)
768.0 KiB + 928.0 KiB = 1.7 MiB bash (13)
2.8 MiB + 118.0 KiB = 2.9 MiB mongod
5.1 MiB + 1.2 MiB = 6.3 MiB python3.3
7.4 MiB + 109.0 KiB = 7.5 MiB tmux [deleted] (2)
---------------------------------
20.3 MiB
=================================
Run Code Online (Sandbox Code Playgroud)
现在,如果我们从函数中删除“del”,并在 test() 之后设置一个断点:
import itertools
import pdb
def test():
a = "a"
for _ in itertools.repeat(None, 30):
a += a
pdb.set_trace()
test()
pdb.set_trace()
Run Code Online (Sandbox Code Playgroud)
在我们终止之前,内存确实不会被释放:
Private + Shared = RAM used Program
4.0 KiB + 9.0 KiB = 13.0 KiB VisualGDB-DisownTTY-r1
4.0 KiB + 15.0 KiB = 19.0 KiB sharing-tests
4.0 KiB + 19.5 KiB = 23.5 KiB dhcpcd
4.0 KiB + 31.5 KiB = 35.5 KiB gdb
4.0 KiB + 36.0 KiB = 40.0 KiB vim [deleted]
4.0 KiB + 38.0 KiB = 42.0 KiB systemd-udevd
40.0 KiB + 10.0 KiB = 50.0 KiB init
24.0 KiB + 135.0 KiB = 159.0 KiB agetty (6)
12.0 KiB + 150.0 KiB = 162.0 KiB su (3)
160.0 KiB + 53.0 KiB = 213.0 KiB crond
172.0 KiB + 81.0 KiB = 253.0 KiB python3.4
628.0 KiB + 219.5 KiB = 847.5 KiB sshd (3)
836.0 KiB + 152.0 KiB = 988.0 KiB syslog-ng (2)
752.0 KiB + 957.0 KiB = 1.7 MiB bash (13)
2.8 MiB + 113.0 KiB = 2.9 MiB mongod
7.4 MiB + 108.0 KiB = 7.6 MiB tmux [deleted] (2)
1.0 GiB + 1.1 MiB = 1.0 GiB python3.3
---------------------------------
1.0 GiB
=================================
Run Code Online (Sandbox Code Playgroud)
那么我的建议是?使用完后删除吸盘即可,不再需要它了;)