【发布时间】:2021-02-28 16:09:36
【问题描述】:
我最近一直在尝试从 CPython 切换到 PyPy,在尝试解决错误时,更准确地说是带有 SIGSEGV 信号的错误 139(因此是分段错误),我试图通过 GC 模块调查垃圾收集通过查看gc.garbage 属性列表。
例如,在 CPython 中,我可以运行以下代码(取自 there 并进行修改)来检查 GC 垃圾列表中的延迟对象:
import gc
gc.set_debug(gc.DEBUG_SAVEALL)
print(gc.get_count())
lst = []
lst.append(lst)
list_id = id(lst)
del lst
gc.collect()
for item in gc.garbage:
print(item) if list_id == id(item) else "pass"
此代码在 CPython 中运行良好,但在 PyPy 中返回以下错误:
AttributeError: module 'gc' has no attribute 'set_debug'
确实,print(dir(gc)),它为 GC 类返回不同的属性和方法列表,而不是为 PyPy 列出 gc.set_debug():
# Under CPython
['DEBUG_COLLECTABLE', 'DEBUG_LEAK', 'DEBUG_SAVEALL', 'DEBUG_STATS', 'DEBUG_UNCOLLECTABLE', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'callbacks', 'collect', 'disable', 'enable', 'garbage', 'get_count', 'get_debug', 'get_objects', 'get_referents', 'get_referrers', 'get_stats', 'get_threshold', 'is_tracked', 'isenabled', 'set_debug', 'set_threshold']
# Under PyPy
['GcCollectStepStats', 'GcRef', '__doc__', '__loader__', '__name__', '__package__', '__spec__', '_dump_rpy_heap', '_get_stats', 'collect', 'collect_step', 'disable', 'disable_finalizers', 'dump_rpy_heap', 'enable', 'enable_finalizers', 'garbage', 'get_objects', 'get_referents', 'get_referrers', 'get_rpy_memory_usage', 'get_rpy_referents', 'get_rpy_roots', 'get_rpy_type_index', 'get_stats', 'get_typeids_list', 'get_typeids_z', 'hooks', 'isenabled']
如果我理解正确,设置gc.set_debug(gc.DEBUG_SAVEALL) 会将无法访问的对象保留在GC 的垃圾列表中,因此如果没有它,gc.collect() 将尝试释放对象的内存分配。但是我之前想检查一下垃圾列表,因为我怀疑它会触发我正在尝试跟踪的分段错误。
尽管查看了 PyPy 关于垃圾收集的文档(如 here,
here) 和其他地方(如 here 或 here),我无法像在 CPython 中那样在 PyPy 中找到一种方法来仔细观察垃圾收集过程。那么,有人可以向我解释一下 PyPy 和 CPython 的 GC 之间的差异如何影响上述测试代码,更准确地说,如何在使用 PyPy 收集之前查看 gc.garbage 中的待处理对象?
我正在运行 Python 3.6.9 和 PyPy 7.3.2。 GCC 对于 CPython 是 8.4.0,对于 PyPy 是 7.3.1。
【问题讨论】:
标签: python garbage-collection cpython pypy