Python 中的垃圾回收机制是如何工作的?

CPython 中垃圾回收的主要思路

1.维护引用计数器 。对于每一个对象,都有一个对于该对象的引用次数的计数器。如果这个计数器的值减为了 0 ,这就代表这个对象在程序中已经没用了,那么该对象所占用的内存就会被释放。

2.定期检测是否循环引用。 当引用计数器的值下降到 0 时来释放内存的机制并不适用于所有的情况。假如两个对象 A 和 B ,其中 A 拥有对 B 的引用,B 拥有对 A 的引用。 这就称之为循环引用。在这种情况下,这两个对象也没有存在的价值了,此时 A 和 B 都应该被垃圾回收处理。但是,这两个对象的引用计数值不为零, 所以内存会一直被占用。为了解决这个问题,CPython 通过使用算法来检测是否存在循环引用并释放循环引用中的对象。

3.通过启发式算法提升性能。 越晚创建的对象更可能需要被回收。 CPython 引入了一个 分代回收 的概念来判断一个对象使用的相对年龄。年轻一代是指最新被创建出来的对象,而老一代则代表早前创建的对象。每个对象都确定的属于某一代。 当垃圾回收机制执行时, CPython 会优先尝试回收年轻一代的对象。CPython 会定期回收老一代的对象 (由启发式算法确定该回收执行的效率).

垃圾回收循环

了解 CPython 垃圾回收的运作周期是非常有益的。我们创建一个对象来观察垃圾回收机制的运作:

Python 需要配置一个新的对象。为此,它调用 _PyObject_GC_Malloc,给这个对象分配内存以及将其添加到垃圾回收的第一阶段(我们称为 0 代)。 随即查看这个对象在 0 代中的数值是否超过阈值。如果确实超过阈值,而且垃圾回收机制当前没有运作,对 collect_generations 的调用随机生效进行垃圾回收。否则对象正常分配内存。

当 collect_generations 被调用,Python 开始垃圾回收。这个方法算出什么阶段进行垃圾回收 (CPython 默认有三代,但 GC 模块可以修改.。此外,年轻一代拥有低级索引,所以 0 代是最年轻的一代)。Python 循环所有代 (从最老到最年轻) 然后检测某一代的对象值超过阈值。如果有,它会将所有年轻代合并到 这一代然后调用 collect 对这一代进行垃圾回收 。注意: Python 希望最好在 0 代进行垃圾回收, 因为这一代拥有最年轻的对象,同样也能迭代最少。对老一代进行垃圾回收相当于收集所有对象因为对第 i 代的垃圾回收会使用从 0 到 i 代的所有对象。

collect 会对特定代进行垃圾回收。这相当于运行参考循环检测算法 (待会介绍) 然后在特定代找出一系列可得到和不可得到的对象。 这些可得到的对象会被并入下一高级的代 (也就是说,如果 collect 在第 i 代运行,第 i 代的对象会被合并到 i+1 代)。对于不可获得的对象, CPython 会进行所有可能的终结器回调,使弱 ref 回调,最终解除这些对象分配。

最后,垃圾回收模块的内部状态会更新为 collect 完成它的职责。

来源:PY学习网:原文地址:https://www.py.cn/article.html

hmoban主题是根据ripro二开的主题,极致后台体验,无插件,集成会员系统
自学咖网 » Python 中的垃圾回收机制是如何工作的?