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

Eri*_*ban 3 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")
Run Code Online (Sandbox Code Playgroud)

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

sha*_*ang 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进程的内存占用增加,有些调用使其再次减少.所以这一切都取决于分配器如何重新使用内存.