了解 CPython 垃圾收集世代

Understanding Cpython garbage collection generations

我正在努力提高我对 python 中内存管理如何工作的理解,但我对 python 垃圾收集器模块中的世代概念感到困惑。

我的理解如下:

创建的所有对象都从第 0 代开始,一旦达到阈值(第 0 代默认为 700)python 将 运行 该代上的集合和任何幸存的对象进入下一个将军

鉴于以上情况,我无法理解以下输出。

import gc
import sys
x = 1
print(gc.get_count())
gc.collect()
print(gc.get_count())

输出

(64, 1, 1)
(0, 0, 0)

首先,我只有 运行 1 行代码,而且我已经在第 1 代和第 2 代中得到了对象,这意味着垃圾收集至少已经发生了两次,这怎么可能?无论如何要找出每一代中的对象是什么? 第二, 为什么我收集后所有世代的引用都是0?我仍然可以 运行 命令 print(x) 而不会出现错误。这是否意味着仍然有对 x 的引用,因此它应该存在于其中的几代中?

gc.get_count() 显示每一代的计数器,接近阈值。

不是每一代中的对象数量,而是计数器,当它达到 threadshold 时,将为该代发生收集。

例如,如果我从计数器上的 (0,0,0) 开始,运行ning x = [[] for i in range(100)] 会将计数器设置为 (101,0,0)

运行 y = [[] for i in range(600)] 将导致计数器翻转到 (0,1,0) 并且 gen0 收集将 运行。在这一点上,我的所有列表都将移动到 gen1,因为它们在 gen0 集合中幸存下来。

当计数器达到 (699,699,0) 并且分配了另一个对象时,将发生 gen0gen1 收集并且计数器将转到 (0,0,1)。当计数器达到 (699,699,699) 并且分配了一个对象时, 或者您使用 gc.collect()(运行s gen2 集合),计数器将重置回 (0,0,0).

要获取每一代中的对象,请使用 gc.get_objects(gen)

关于代码 运行s 之前的垃圾收集 - 当 Python 启动时,它甚至在加载脚本之前就创建了很多对象。例如,您可以看到 运行ning sys.modules 加载的模块。创建这些对象时,垃圾收集器 运行 会自动启动。