如何将内存从Python释放回操作系统?

如何将内存从Python释放回操作系统?,python,python-2.7,garbage-collection,multiprocessing,psutil,Python,Python 2.7,Garbage Collection,Multiprocessing,Psutil,我的代码与此类似: def memoryIntensiveFunction(x): largeTempVariable = Intermediate(x) processFunction(largeTempVariable,x) 问题是,在我的测试用例中,变量temp大约为500 mb,但当memoryIntensiveFunction完成时,该空间不会返回给操作系统。我之所以知道这一点,是因为使用guppy工具进行内存评测时说largeTempVariable是被释放的(即在

我的代码与此类似:

def memoryIntensiveFunction(x):
    largeTempVariable = Intermediate(x)
    processFunction(largeTempVariable,x)
问题是,在我的测试用例中,变量
temp
大约为500 mb,但当
memoryIntensiveFunction
完成时,该空间不会返回给操作系统。我之所以知道这一点,是因为使用
guppy
工具进行内存评测时说
largeTempVariable
是被释放的(即在Python中),但
psutil
显示不是。我想我看到了描述的效果。问题是这个进程运行时间很长(即数小时),
memoryIntensiveFunction
在一开始就运行,以后再也不会运行了,所以我很不方便将500mb传输数小时

我找到了一个解决方案,建议使用单独的流程。多道处理会产生自己的成本,但在我的情况下,这是值得的。但是,这需要重构
memoryIntensiveFunction
调用者接收
x
作为返回值,而不是看到它被修改到位。真正的杀手是我的对象
x
不可拾取(它大量使用boostpython扩展)。要使
x
pickable成为可拾取的,需要做很多工作


有什么我没有考虑的选择吗?

这似乎很奇怪,我试图复制你的问题,似乎简单的“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()
在第一个断点处,您将看到它使用了大约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
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
=================================
现在,如果我们从函数中删除“del”,并在test()之后设置一个断点:

在我们终止之前,内存确实不会被释放:

 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
=================================

那么我的建议呢?只需在使用完吸盘后将其删除,不再需要它;)

注意,我使用的是Python2.7,因此Python3中可能有内存优化方面的改进。另外,我能够得到一个简单的测试用例,包括创建
[1.0]*10**7
,并且
del
能够像使用
psutil
所观察到的那样释放它,但是我的对象
largeTempVariable
在某种程度上是不平凡的,超出范围并不会将它释放回操作系统。@amos到底是什么?在OP中,你说它是一个大变量——这就是我在测试中使用的,它与2.7的工作方式相同。但现在您似乎表明它不是一个变量而是一个列表?那么它到底是什么呢?它是一个包含dicts、set、嵌套dicts和set等的对象。在底部是点和字符串…@amos,它仍然非常模糊,太模糊了,以至于无法准确指出导致内存未释放问题的原因。考虑到这一点,我只能说,要么重新设计类使其更简单,要么重新设计应用程序使其更原子化,以便将其分解为单独的线程。这可能是操作系统特有的。我相信Linux特别倾向于不回收未使用的内存,因为它假设未使用的内存只在纸上“使用”,也就是说,因为它不是“热”内存,所以它将被交换,这本身就是一个适当的解决方案。
import itertools
import pdb

def test():
    a = "a"
    for _ in itertools.repeat(None, 30):
        a += a
    pdb.set_trace()

test()
pdb.set_trace()
 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
=================================