垃圾收集器是否跟踪了所有Python对象?

时间:2010-11-02 15:25:24

标签: python garbage-collection memory-management

我正在尝试调试内存泄漏(请参阅问题Memory leak in Python Twisted: where is it?)。

当垃圾收集器运行时,是否可以访问Python解释器创建的所有Python对象?如果我们假设Python C库没有泄漏,那么RSS内存使用量是否会相对于GC对象计数线性增长? sys.getobjects怎么样?

2 个答案:

答案 0 :(得分:9)

CPython使用两种机制来清理垃圾。一个是引用计数,它影响所有对象,但不能清除(直接或间接)相互引用的对象。这就是实际垃圾收集器的用武之地:python有gc模块,它在它知道的对象中搜索循环引用。只有可能成为参考周期一部分的对象才需要担心参与循环gc。因此,例如,列表可以,但字符串不会;字符串不引用任何其他对象。 (事实上​​,这个故事有点复杂,因为有两种方式参与循环gc,但这在这里并不重要。)

所有Python类(及其实例)都会被循环gc自动跟踪。 C中定义的类型不是,除非他们付出一点努力。所有可能属于循环的内置类型都可以。但这确实意味着gc模块只知道播放的类型。

除了收集机制之外,还有一个事实是Python有自己的聚合内存分配器(obmalloc),它分配整个内存竞技场,并为它创建的大多数较小的对象使用内存。 Python现在可以释放这些竞技场,因为它们完全是空的(很长一段时间没有),但实际上清空竞技场是相当罕见的:因为CPython对象不可移动,你不能只是将一些落后者移动到另一个舞台。

答案 1 :(得分:0)

RSS不会随着Python对象的数量线性增长,因为Python对象的大小可能不同。 int对象通常比大list小得多。

我想你写gc.get_objects时的意思是sys.getobjects。此函数为您提供所有可到达对象的列表。如果您认为存在泄漏,则可以迭代此列表并尝试查找本应已释放的对象。 (例如,您可能知道某个类型的所有对象都将在某个点被释放。)