在Python中,对象何时被垃圾回收?内存何时释放?垃圾回收是否影响性能?是否可以选择退出或调整GC算法?如果可以,如何操作?
在Python中,对象何时被垃圾回收?内存何时释放?垃圾回收是否影响性能?是否可以选择退出或调整GC算法?如果可以,如何操作?
Python中对象何时被垃圾回收?
在CPython的源代码中有很多细节:http://svn.python.org/view/python/trunk/Modules/gcmodule.c?revision=81029&view=markup
任何时候当一个对象的引用计数降为零,该对象会立即被移除。
293 /* Python的循环垃圾回收不应该看到一个计数为0的引用:
294 * 如果某个东西已经减少到0,那么它应该在那个时候就被
295 * 释放了。
当新对象的数量大于现有对象数量的25%时,将触发完整的垃圾回收。
87 除了各种可配置的阈值之外,我们仅在以下情况下触发全面的垃圾回收:
88 如果比率
89 long_lived_pending / long_lived_total
90 高于给定值(硬编码为25%)。
内存何时被释放?
我只能找到这个信息。
根据这个情况,即使您将对象的引用计数降至零,Python可能仍会将其保留在自由列表中进行回收利用。我无法明确找到何时进行免费调用以将内存返还给操作系统,但我想当进行垃圾回收时,如果对象未保留在自由列表中,则会执行此操作。 垃圾回收是否会影响性能? 我所了解的任何非平凡垃圾收集器都需要CPU和内存才能运行。因此,是的,它总是会对性能产生影响。您需要进行实验并了解您的垃圾收集器。781 /* 清除所有的自由列表
782 * 在收集最高一代的过程中清除所有的自由列表。
783 * 自由列表中分配的项目可能会占用一个pymalloc地区。
784 * 清除自由列表可以更早地将内存返还给操作系统。
785 */
这里是摘自语言参考的一部分:
对象永远不会被显式销毁;但是,当它们变得无法访问时,它们可能会被垃圾收集。 一个实现允许延迟垃圾收集或完全省略垃圾收集 - 垃圾收集的实现方式是实现质量的问题,只要不收集仍然可访问的对象即可。
CPython 实现细节: CPython 目前使用引用计数方案和(可选的)延迟检测循环链接垃圾回收,尽早收集大多数不可访问的对象,但不能保证收集包含循环引用的垃圾。有关控制循环垃圾收集的信息,请参阅gc模块的文档。其他实现方式行为不同,而CPython可能会发生变化。当对象变得无法访问时,不要依赖其立即完成最终处理(例如:始终关闭文件)。
编辑: 关于延迟垃圾回收... gc
模块允许您与垃圾回收器交互,并在需要时禁用它,更改收集频率等。但我自己没有使用过。此外,任何包含__del__
方法的对象的循环不会被收集。
gc
模块的详细信息。 - Praveen Gollakota为了更详细地解释之前的答案并提供更多可操作的信息:
您可以使用 gc.set_threshold(threshold0[, threshold1[, threshold2]])
来调整自动垃圾回收启动的时间:
GC将对象根据它们经历过多少次垃圾回收分类为三代。新对象被放置在最年轻的一代(第0代)。如果一个对象经过一次回收后仍存活,它就会被移动到下一代。由于第2代是最老的一代,所以在回收后该代中的对象仍然留在那里。为了决定何时运行,收集器跟踪自上次回收以来的对象分配和取消分配数量。当分配数量减去取消分配数量超过threshold0时,就开始进行回收。最初只检查第0代。如果第0代自检查以来已经检查了超过threshold1次,那么也会检查第1代。对于第三代,情况略微复杂,请参见收集最老一代以获取更多信息。
虽然我在文档中找不到默认阈值,但是通过实现的查看,阈值的默认值似乎是(CPython 3.9.1):
threshold0
: 700threshold1
: 10threshold2
: 10也就是说,默认情况下,自动垃圾回收应该在分配数减去释放数超过700时启动。