【问题标题】:Force garbage collection in Python to free memory在 Python 中强制垃圾回收以释放内存
【发布时间】:2015-11-16 23:54:36
【问题描述】:

我有一个 Python2.7 应用程序,它使用了很多 dict 对象,这些对象主要包含键和值的字符串。

有时不再需要这些字典和字符串,我想将它们从内存中删除。

我尝试了不同的东西,del dict[key]del dict 等。但应用程序仍然使用相同数量的内存。

下面是一个我希望为内存付费的示例。但它没有:(

import gc
import resource

def mem():
    print('Memory usage         : % 2.2f MB' % round(
        resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/1024.0/1024.0,1)
    )

mem()

print('...creating list of dicts...')
n = 10000
l = []
for i in xrange(n):
    a = 1000*'a'
    b = 1000*'b'
    l.append({ 'a' : a, 'b' : b })

mem()

print('...deleting list items...')

for i in xrange(n):
    l.pop(0)

mem()

print('GC collected objects : %d' % gc.collect())

mem()

输出:

Memory usage         :  4.30 MB
...creating list of dicts...
Memory usage         :  36.70 MB
...deleting list items...
Memory usage         :  36.70 MB
GC collected objects : 0
Memory usage         :  36.70 MB

我希望在这里“收集”一些对象并释放一些内存。

我做错了吗?任何其他删除未使用对象或至少查找意外使用对象的位置的方法。

【问题讨论】:

  • 然后做gc.collect()

标签: python python-2.7 memory memory-management garbage-collection


【解决方案1】:

这可能有点用,使用多处理和一个名为 Ray 的库,它使用共享内存在进程之间执行多 GB 数据共享。这种方式很容易生成辅助进程,并且仍然可以从父进程快速轻松地访问相同的对象。

【讨论】:

    【解决方案2】:

    Frederick Lundh explains,

    如果你创建一个大对象并再次删除它,Python 可能已经释放了 内存,但所涉及的内存分配器不一定返回 内存到操作系统,所以它看起来好像 Python 进程使用 比实际使用的虚拟内存多得多。

    and Alex Martelli writes

    唯一真正可靠的方法可以确保大型但 内存的临时使用确实在完成后将所有资源返回给系统, 是让这种使用发生在一个子进程中,它完成了需要大量内存的工作 然后终止。

    因此,您可以使用multiprocessing 生成一个子进程,执行内存占用计算,然后确保在子进程终止时释放内存:

    import multiprocessing as mp
    import resource
    
    def mem():
        print('Memory usage         : % 2.2f MB' % round(
            resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/1024.0,1)
        )
    
    mem()
    
    def memoryhog():
        print('...creating list of dicts...')
        n = 10**5
        l = []
        for i in xrange(n):
            a = 1000*'a'
            b = 1000*'b'
            l.append({ 'a' : a, 'b' : b })
        mem()
    
    proc = mp.Process(target=memoryhog)
    proc.start()
    proc.join()
    
    mem()
    

    产量

    Memory usage         :  5.80 MB
    ...creating list of dicts...
    Memory usage         :  234.20 MB
    Memory usage         :  5.90 MB
    

    【讨论】:

    • 我认为我们的应用程序不可能做到这一点(作为快速修复)。许多对象是共享的,需要在应用程序的不同部分进行访问。但是在您的示例中,第二个 Mem usage... 应该会产生更多内存,您不觉得吗?
    • Python 内存分配很复杂。它创建用于分配给对象的内存池,并且不能将内存池返回给操作系统,除非整个池为空且未分段。此外,许多内置类型保留了以前分配的项目的“空闲列表”,以便将来为相同类型重用,而不是创建新的内存分配。
    • @ddofborg:我机器的getrusage 报告了最大驻留集大小,以千字节为单位,而不是字节。
    • @MattAnderson 好的,我知道这很复杂。您的意思是在处理大量数据后无法将内存释放给操作系统?
    • @ddofborg - 在深入了解一两次 cpython 2.7 内存管理之后,我团队的生产级策略是在自己的进程中进行任何巨大的内存需求处理并退出,并让操作系统清理完成后追上它。尝试将“命令和控制”过程保持在合理的大小(在我们的例子中为 500MB - 1GB)。内存能否归还给操作系统取决于分配的对象以及碎片内存的获取方式。通过阅读 Python 3.x 发行说明,3 系列解释器的情况可能有所改善。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-22
    • 2019-05-15
    • 1970-01-01
    相关资源
    最近更新 更多