为什么仅分配原子类型时CPython的垃圾回收器(GC)仍会被触发?
IPython环境下执行简单赋值触发GC的原因
你的猜测完全正确,该现象确实由IPython内部分配的被GC追踪的隐藏对象导致,核心逻辑如下:
- CPython的GC触发规则是基于可追踪对象的分配计数:每生成一个被GC追踪的对象(绝大多数容器类对象都属于此类),对应回收代的分配计数就会+1,计数达到预设阈值时就会自动触发全量或对应代的GC,该计数统计的是整个Python进程内所有的可追踪对象分配,和用户代码是否直接生成可追踪对象无关。
- IPython内核为了实现交互式功能,每执行一行用户输入的语句时,都会产生大量额外的可追踪对象:包括但不限于存储输入记录的
In列表、存储输出记录的Out字典、代码解析生成的临时AST节点、历史记录维护用到的容器对象、补全提示逻辑生成的临时对象等。你每执行一次x=0,IPython后台就会分配数个被GC追踪的容器对象,累计到阈值后自然就会触发GC。 - 原生
python -i启动的交互式进程没有该问题,是因为原生解释器的额外开销极低,默认不会在Python层面留存所有输入输出历史(方向键可调取的历史存储在C语言层面,不会生成Python可追踪对象),执行简单赋值时没有额外的可追踪对象分配,只有用户主动生成列表、字典、自定义类实例等可追踪对象时,才会累计分配计数触发GC,和文档描述的行为一致。
你可以通过以下方式验证该结论:在IPython和原生Python交互环境中,每次执行x=0后调用gc.get_count()查看当前的GC代计数,IPython环境下计数会随执行次数明显上涨,原生Python环境下计数几乎不会变化。
内容的提问来源于stack exchange,提问作者BatWannaBe
相关产品推荐
相关产品推荐

