Python 的 GC - 从get_count获取对象



我正试图了解从gc.get_countgc.get_objects()返回的值之间的差异。

首先,文档(https://docs.python.org/3.8/library/gc.html)说:

gc.get_count((

将当前集合计数作为(count0,count2(。

gc.get_objects(generation=None(

返回收集器跟踪的所有对象的列表,不包括返回的列表。如果generation不是None,则只返回该generation中收集器跟踪的对象。

现在,在一个简单的REPL上运行:

> import gc
> gc.get_count()
(692, 1, 1)
> len(gc.get_objects())
6372
> len(gc.get_objects(0))
771
> len(gc.get_objects(1))
490
> len(gc.get_objects(2))
5111
> gc.get_count()
(693, 1, 1)

因此,从get_count开始,三代人总共有大约700个对象。然而CCD_ 4返回>6k个对象。我试图研究DEBUG_SAVEALL,但它似乎与任何数字都不相关(不在get_count中,也不在get_objects中(。

我的问题是:

  1. 为什么会出现差异?get_objects中的对象和get_count中跟踪的对象之间的实际区别是什么?stackoverflow上有两个问题:第一个和第二个,但它们似乎无法回答差异
  2. 我如何实际获得get_count中引用的对象(用于特定的一代(

谢谢!

所以我对CPython实现有一些了解(https://github.com/python/cpython/blob/master/Modules/gcmodule.c)这就是我学到的:

1(

基本上是get_count(此处简称:https://github.com/python/cpython/blob/master/Modules/gcmodule.c#L1636-L1645(测量在低一级生成中发生的收集量,直到该生成本身被收集为止(参见此处:https://github.com/python/cpython/blob/master/Modules/gcmodule.c#L1211-L1212(。

因此,例如,当收集第0代(第一代(时,第1代的计数将增加1。第0代的计数在分配时增加,在解除分配时减少(集合在#allocations - #deallocations > threashold时开始(。

这回答了问题(1(——差异是因为它们是完全不同的东西。


2(

既然问题1已经回答了,那么问题2在被问到时实际上是不相关的

然而,我们可能会问一个不同的问题,即";如何跟踪为特定一代收集的对象">

使用Python 3.8,这是可能的,因为CCD_;归属;到特定的一代。考虑到这一点,可以注册一个回调(通过gc.callbacks.append(callback_method)(,通过在清理对象之前获取对象(但请注意,您不想实际强引用这些对象,否则您将仅通过测量来改变行为(,然后获取对象,并比较结果,来跟踪特定生成的集合。


由于我在回答自己的问题,我将在一段时间内不接受这个答案,以便有机会获得其他答案。

最新更新