【问题标题】:Are all Python objects tracked by the garbage collector?垃圾收集器是否跟踪所有 Python 对象?
【发布时间】:2010-11-02 15:25:24
【问题描述】:

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

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

【问题讨论】:

    标签: python garbage-collection memory-management


    【解决方案1】:

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

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

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

    【讨论】:

    • 好的,这意味着查看 GC 引用的对象不足以解释内存泄漏。例如,可能有一个字符串增长到无限。很难弄清楚 Python 分配器永久保留的数量以及泄漏的数量。
    • 嗯,它不可能是一个正在增长的 string,因为字符串是不可变的(它们不能改变,所以它们不能增长。)它可能是新的分配的字符串越来越大,当然会破坏旧的字符串。或者它可能是一个不断增长的列表;这将是同一个对象,但它会变得更大。
    【解决方案2】:

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

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

    【讨论】:

    • 但我认为 RSS 的趋势仍应与对象计数相同。如果列表很大,则意味着它将包含很多对象(增加对象数量)。除非一个未被 GC 计数的对象增长了很多(例如字符串)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-29
    • 1970-01-01
    相关资源
    最近更新 更多