使用Cython指令no_gc

时间:2016-11-09 19:08:54

标签: python garbage-collection cython

在Cython 0.25中添加了no_gc指令。可以找到这个新指令(以及相关的no_gc_clear指令)的文档here,但我唯一真正理解的是它可以加速你的代码禁用某些方面垃圾收集。

我感兴趣,因为我有一些使用扩展类型的高性能Cython代码,我知道no_gc可以进一步加快速度。在我的代码中,扩展类型的实例总是处于活动状态,直到程序关闭的最后,这让我觉得禁用垃圾收集可能没问题。

我想我真正需要的是一个例子,其中no_gc的使用变为错误并导致内存泄漏,同时解释了为什么会发生这种情况。

1 个答案:

答案 0 :(得分:1)

与循环引用有关 - 当实例a持有对再次引用a的Python对象的引用时,a永远不会通过引用计数释放,因此Python会尝试检测循环。

可能导致问题的类的一个非常试验示例是:

# Cython code:

cdef class A:
    cdef param

    def __init__(self):
        self.param = self

(以及一些运行它的Python代码)

import cython_module
while True:
    cython_module.A()

这很好(检测到周期并且它们经常被解除分配)但是如果你添加no_gc那么你的内存就会用完。

更现实的例子可能是存储彼此引用的父/子对。

值得补充的是,性能提升可能很小。垃圾收集器仅在分配了大量对象且很少被释放的情况下偶尔运行(https://docs.python.org/3/library/gc.html - 请参阅set_threshold)。希望这不太可能描述您的高性能代码。

使用GC分配和释放对象时,可能还会产生很小的性能成本,以便在跟踪对象列表中添加/删除它们(但同样,希望您没有分配/取消分配大量数据)

最后,如果你的类从不存储对Python对象的任何引用,那么无论如何它都是有效的no_gc。设置选项不会有害,但也没有好处。