Python 2.6 GC似乎可以清理对象,但不会释放内存

时间:2011-02-09 19:09:54

标签: python memory memory-leaks

我有一个用python 2.6编写的程序,它创建了大量的短期实例(这是一个典型的生产者 - 消费者问题)。我注意到top和pmap报告的内存使用情况似乎在创建这些实例时会增加,并且永远不会再次下降。我担心我使用的一些python模块可能会泄漏内存,所以我仔细隔离了代码中的问题。然后我开始尽可能简短地再现它。我想出了这个:

class LeaksMemory(list):
    timesDelCalled = 0

    def __del__(self):
        LeaksMemory.timesDelCalled +=1


def leakSomeMemory():
    l = []
    for i in range(0,500000):
        ml = LeaksMemory()
        ml.append(float(i))
        ml.append(float(i*2))
        ml.append(float(i*3))
        l.append(ml)

import gc
import os


leakSomeMemory()

print("__del__ was called " + str(LeaksMemory.timesDelCalled) + " times")
print(str(gc.collect())  +" objects collected")
print("__del__ was called " + str(LeaksMemory.timesDelCalled) + " times")
print(str(os.getpid()) + " : check memory usage with pmap or top")

如果你用'python2.6 -i memoryleak.py'之类的东西运行它会暂停,你可以使用pmap -x PID来检查内存使用情况。我添加了 del 方法,以便我可以验证GC是否正在发生。它不在我的实际程序中,似乎没有任何功能差异。每次调用leakSomeMemory()都会增加此程序消耗的内存量。我担心我会犯一些简单的错误,并且参考文件会被意外保留,但无法识别它。

2 个答案:

答案 0 :(得分:8)

Python将释放对象,但不会立即将内存释放回操作系统。相反,它将在同一个解释器中重用相同的段以用于将来的分配。

以下是关于此问题的博文:http://effbot.org/pyfaq/why-doesnt-python-release-the-memory-when-i-delete-a-large-object.htm

更新:我自己使用Python 2.6.4测试了这一点,并没有注意到内存使用量的持续增加。一些leakSomeMemory()的调用导致Python进程的内存占用增加,有些使其再次减少。所以这一切都取决于分配器如何重新使用内存。

答案 1 :(得分:4)

根据Alex Martelli

  

“唯一真正可靠的方式   确保大量但临时使用   内存将返回所有资源   系统何时完成,就是拥有   这种用法发生在一个子进程中   那时需要记忆力的工作   终止“。

因此,在您的情况下,使用multiprocessing模块在​​单独的进程中运行短期函数以确保在进程完成时返回资源是有意义的。

import multiprocessing as mp

def NOT_leakSomeMemory():
    # do stuff
    return result


if __name__=='__main__':
    pool = mp.Pool()
    results=pool.map(NOT_leakSomeMemory, range(500000)) 

有关如何使用多处理进行设置的更多提示,请参阅Doug Hellman's tutorial