在python中,对象何时被垃圾收集?

在python中,对象何时被垃圾收集?,python,memory-management,garbage-collection,Python,Memory Management,Garbage Collection,在python中,对象何时被垃圾收集?内存何时释放?收集是否会影响性能?一个人可以选择退出或调整gc算法吗?如果是的话,如何调整?以下是 物体永远不会被明确摧毁;但是,当它们变得无法访问时,可能会被垃圾收集允许一个实现推迟垃圾收集或完全忽略垃圾收集-只要没有收集到仍然可以访问的对象,垃圾收集的实现方式取决于实现质量 CPython实现详细信息:CPython当前使用一种引用计数方案,该方案具有(可选)延迟检测循环链接垃圾的功能,它会在无法访问大多数对象时立即收集这些对象,但不保证收集包含循环引用

在python中,对象何时被垃圾收集?内存何时释放?收集是否会影响性能?一个人可以选择退出或调整gc算法吗?如果是的话,如何调整?

以下是

物体永远不会被明确摧毁;但是,当它们变得无法访问时,可能会被垃圾收集允许一个实现推迟垃圾收集或完全忽略垃圾收集-只要没有收集到仍然可以访问的对象,垃圾收集的实现方式取决于实现质量

CPython实现详细信息:CPython当前使用一种引用计数方案,该方案具有(可选)延迟检测循环链接垃圾的功能,它会在无法访问大多数对象时立即收集这些对象,但不保证收集包含循环引用的垃圾。有关控制循环垃圾收集的信息,请参阅gc模块的文档。其他实现的行为不同,CPython可能会发生变化。当对象变得不可访问时,不要依赖于对象的立即终结(例如:始终关闭文件)


编辑:关于推迟垃圾收集。。。。该模块允许您与垃圾收集器交互,如果您想禁用它并更改收集频率等,可以禁用它。但我自己没有使用过它。另外,包含具有
\uu del\uu
方法的任何对象的循环。

在python中何时对对象进行垃圾收集?

CPython的源代码中有很多细节:

每当引用计数降至零时,对象将立即删除

293/*Python的循环gc永远不会看到传入的refcount

294*of 0:如果某个值减为0,则该值应为

295*当时立即解除分配

当新对象数大于现有对象数的25%时,将触发完整集合

87除了各种可配置的阈值外,我们只触发

88如果比率为

89长寿命待定/长寿命总数

90高于给定值(硬连线到25%)

内存何时释放?

我只能找到这些信息

781/*清除所有免费列表

782*在收集最高级别的 一代人

783*免费列表中的已分配项目可以保留pymalloc竞技场 有事

784*清除空闲列表可能会更早地将内存返回操作系统

785*/

根据这一点,Python可能会将您的对象保留在一个免费列表中,以便循环使用,即使您将其refcount降至零。我无法明确地找到何时进行空闲调用以将内存返回给操作系统,但我认为只要进行了一次收集并且对象没有保留在空闲列表中,就会执行此操作

收藏是否会影响性能?

我听说过的任何非平凡的垃圾收集器都需要CPU和内存才能运行。因此,是的,总是会对性能产生影响。你必须进行实验,了解你的垃圾收集器


需要实时响应的程序遇到了问题,因为垃圾收集器不能让我控制它们何时运行或运行多长时间。一些特殊情况也会导致内存过度使用,例如Python保留空闲列表的诀窍。

要用更多数字和可操作信息来扩展前面的答案:

您可以使用在自动垃圾收集开始时进行调整:

GC根据对象的数量将对象分为三代 他们幸存下来了。新对象将放置在 最年轻的一代(第0代)。如果对象在集合中幸存 它被移植到下一代。因为第二代是 最古老的一代,该代中的对象在一段时间后仍保留在那里 收集为了决定何时运行,收集器会跟踪 自上次 收集当分配的数量减去 解除分配超过阈值0,集合开始。最初只是 检查第0代。如果第0代已检查超过 自检查第1代起,阈值为1次,然后 1也进行了检查。对于第三代,事情有点复杂 更复杂的,参见

虽然我在文档中找不到默认阈值,但通过查看实现,阈值的默认值(CPython 3.9.1):

  • 阈值0
    :700
  • 阈值1
    :10
  • 阈值2
    :10

也就是说,默认情况下,一旦分配数减去释放数超过700,则应设置自动垃圾回收。

Nice,尽管相当错误。知道你是如何发射或推迟gc的吗?马特·阿尔科克(Matt Alcock)提出了一个不同的问题,答案是肯定的。通常高性能系统会想发射gc以保证一致的性能——想象一下飞行控制系统在垃圾收集时超时一段时间?@MattAlcock在post.@Mattalock:高性能系统通常不使用任何类型的动态内存分配。当我制作雷达和声纳时,数据结构是严格静态分配的。在高性能系统中使用任何动态内存分配的想法似乎是矛盾的。在Python中关闭垃圾收集通常是通过用C编写性能关键的代码并从Python中调用来完成的