首页 > 解决方案 > 在覆盖该引用之前删除对大型 Python 对象的引用有什么好处吗?

问题描述

我正在运行一些对数据库中的文档进行迭代的大量内存脚本,并且由于服务器上的内存限制,我在每次迭代结束时手动删除了对大对象的引用:

for document in database:
    initial_function_calls()

    big_object = memory_heavy_operation(document)
    save_to_file(big_object)

    del big_object

    additional_function_calls()

initial_function_calls()additional_function_calls()略微占用大量内存。通过显式删除对垃圾收集的大对象的引用,我是否看到了任何好处?或者,离开它并让它在下一次迭代中指向一个新对象就足够了吗?

标签: pythongarbage-collection

解决方案


通常在这些情况下;这取决于。:-/

我假设我们在这里谈论的是 CPython。

使用del或重新分配名称会减少对象的引用计数。只有当该引用可以达到 0 时,它才能被取消分配。因此,如果您无意中将对某处的引用藏在big_object了某个地方,那么使用del将无济于事。

何时触发垃圾收集取决于分配和取消分配的数量。请参阅gc.set_threshold().

如果您很确定没有进一步的引用,您可以使用强制gc.collect()垃圾收集运行。如果您的代码没有进行很多其他分配,这可能会有所帮助。

要记住的一件事是,如果big_object是由C扩展模块(例如numpy)创建的,它可以管理自己的内存。在那种情况下,垃圾收集不会影响它!小整数和小字符串也是预先分配的,不会被垃圾收集。您可以使用它gc.is_tracked()来检查对象是否由垃圾收集器管理。

我建议您在有和没有del+的情况下运行程序gc.collect(),并监控使用的 RAM 量。在类 UNIX 系统上,查看resident set size。你也可以使用sys._debugmallocstats().

除非您看到驻留集大小不断增长,否则我不会担心。


推荐阅读