Python 垃圾回收机制详解
什么是垃圾回收机制
Python 中的垃圾回收机制是自动的内存管理系统,可以帮助开发人员避免手动管理内存带来的问题。在 Python 中,通过垃圾回收机制来监控和清理程序中不再需要的对象。
Python 的垃圾回收机制的实现
引用计数
Python 中最基本的垃圾回收策略是引用计数,即解释器维护每个对象的引用计数,当计数为 0 时,对象就会被销毁。例如:
a = 1
b = a # a 和 b 都引用了同一个整数对象
a = None # a 不再引用整数对象
# 这时对象的引用计数变为 1,对象不会被销毁
b = None
# 对象的引用计数变为 0,对象被销毁
Python 中主要对象类型的引用计数更新如下:
- 赋值语句增加引用计数;
- 赋值语句覆盖引用更新;
- 对象作为参数传递给函数时计数增加;
- 其他引用对象的操作均引起计数变化。
引用计数的优点是实现简单,缺点是对于循环引用(两个对象相互引用,但是其他对象不再引用它们)的处理不起作用。
标记-清除算法
当引用计数不能解决循环引用的问题时,Python 会使用标记-清除算法。标记-清除算法分为两个阶段:
- 标记阶段:遍历内存中所有对象,标记所有可达(reachable)对象,即从根对象(global、local等)出发,可达的对象都被视为存活(live)对象
- 清除阶段:遍历内存中所有对象,清除所有未标记的对象
示例代码:
def demo():
a = [1, 2]
b = [3, 4]
a.append(b)
b.append(a)
del a
del b
demo()
当 demo 函数运行完毕,可以发现 a 和 b 都被置为 None,但是 [1, 2] 和 [3, 4] 之间的循环引用依旧存在。此时标记-清除算法就可以起作用,在第一阶段中将从根对象出发可以访问到的所有对象标记为可达,第二阶段中清除未被标记的对象。
分代回收
Python 的分代回收算法基于一条简单的原则:新对象容易死亡,老对象容易存活。即刚创建的对象是“垃圾对象”的可能性更大,而生命周期较长的对象则更可能一直存活。Python 的实现中,将对象分为三类:
- 第 0 代对象(youngsters):新分配的对象
- 第 1 代对象(young adults):survivors,经过一次垃圾回收后仍然存活的 young objects
- 第 2 代对象(old men):经过多次垃圾回收后仍然存活的对象
每个对象都有一个代数计数器,当对象新创建时为 0,每次经过垃圾回收时增加 1。对于这三类对象,Python 分别使用不同的策略:
- 第 0 代对象:使用引用计数策略
- 第 1 代和第 2 代对象:使用标记-清除策略
在内存分配过程中,新对象会被放到第 0 代中。当此代占满时,Python 将进行第 0 代垃圾回收,清理其中的垃圾对象。经过垃圾回收后,仍然存活的对象会被移动到第 1 代中。第 1 代内存占满时,Python 进行第 1 代垃圾回收,清理其中的垃圾对象。存活的对象会被移动到第 2 代中。第 2 代内存达到一定大小时,Python 进行第 2 代垃圾回收,清理其中的垃圾对象并将 remaining survivors 移回第 1 代中。
一个简单的例子如下:
class MyClass:
pass
if __name__ == '__main__':
objs = []
for i in range(10000000):
objs.append(MyClass())
上述代码会构造 10000000 个实例,Python 需要运用垃圾回收机制来释放其中的垃圾内存。可以使用 tracemalloc 模块来检测 Python 的内存使用情况,示例代码如下:
import tracemalloc
class MyClass:
pass
if __name__ == '__main__':
tracemalloc.start()
objs = []
for i in range(10000000):
objs.append(MyClass())
del objs
tracemalloc.stop()
print(tracemalloc.get_traced_memory())
运行结果会输出 Python 的内存占用情况,可以通过调整 tracemalloc 的参数来观察内存使用情况的变化。
总结
Python 的垃圾回收机制主要有三个方面:引用计数、标记-清除算法和分代回收。引用计数是 Python 最基本的垃圾回收策略,标记-清除算法则用于处理循环引用,分代回收则基于新对象容易死亡,老对象容易存活的原则,对不同生命周期的对象采用不同的回收策略。在实际开发中,了解 Python 的垃圾回收机制,对于程序的性能优化和内存管理非常重要。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Python 垃圾回收机制详解 - Python技术站