在覆盖该引用之前删除对大型 Python 对象的引用有什么好处吗?
Is there any benefit to deleting a reference to a large Python object before overwriting that reference?
我是 运行 一些内存密集型脚本,它遍历数据库中的文档,由于服务器上的内存限制,我在每次迭代结束时手动删除对大对象的引用:
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()
都略显占用内存。通过显式删除对用于垃圾收集的大对象的引用,我是否看到任何好处?或者,在下一次迭代中保留它并让它指向一个新对象就足够了吗?
在这些情况下很常见;这取决于。 :-/
我假设我们在这里谈论的是 CPython。
使用del
或重新分配名称会减少对象的引用计数。只有当该引用可以达到 0 时,它才能被取消分配。因此,如果您无意中将对 big_object
的引用隐藏在某个地方,使用 del
将无济于事。
何时触发垃圾收集取决于分配和取消分配的数量。请参阅 gc.set_threshold()
的文档。
如果您非常确定没有进一步的引用,您可以使用 gc.collect()
来 强制 垃圾收集 运行。如果您的代码不进行大量其他分配,这可能会有所帮助。
要记住的一件事是,如果 big_object
是由 C
扩展模块(例如 numpy
)创建的,它可以管理自己的内存。在那种情况下,垃圾收集不会影响它!小整数和小字符串也是预先分配的,不会被垃圾收集。您可以使用 gc.is_tracked()
检查对象是否由垃圾收集器管理。
我建议您 运行 您的程序使用和不使用 del
+gc.collect()
,并监控使用的 RAM 量。在类 UNIX 系统上,查看 驻留集大小 。您也可以使用 sys._debugmallocstats()
.
除非你看到驻留集的大小越来越大,否则我不会担心。
我是 运行 一些内存密集型脚本,它遍历数据库中的文档,由于服务器上的内存限制,我在每次迭代结束时手动删除对大对象的引用:
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()
都略显占用内存。通过显式删除对用于垃圾收集的大对象的引用,我是否看到任何好处?或者,在下一次迭代中保留它并让它指向一个新对象就足够了吗?
在这些情况下很常见;这取决于。 :-/
我假设我们在这里谈论的是 CPython。
使用del
或重新分配名称会减少对象的引用计数。只有当该引用可以达到 0 时,它才能被取消分配。因此,如果您无意中将对 big_object
的引用隐藏在某个地方,使用 del
将无济于事。
何时触发垃圾收集取决于分配和取消分配的数量。请参阅 gc.set_threshold()
的文档。
如果您非常确定没有进一步的引用,您可以使用 gc.collect()
来 强制 垃圾收集 运行。如果您的代码不进行大量其他分配,这可能会有所帮助。
要记住的一件事是,如果 big_object
是由 C
扩展模块(例如 numpy
)创建的,它可以管理自己的内存。在那种情况下,垃圾收集不会影响它!小整数和小字符串也是预先分配的,不会被垃圾收集。您可以使用 gc.is_tracked()
检查对象是否由垃圾收集器管理。
我建议您 运行 您的程序使用和不使用 del
+gc.collect()
,并监控使用的 RAM 量。在类 UNIX 系统上,查看 驻留集大小 。您也可以使用 sys._debugmallocstats()
.
除非你看到驻留集的大小越来越大,否则我不会担心。