📜  Python中的垃圾收集(1)

📅  最后修改于: 2023-12-03 15:19:28.494000             🧑  作者: Mango

Python中的垃圾收集

Python中的垃圾收集是自动进行的。Python使用了引用计数器(referee count)来跟踪对象的引用次数。当对象被引用时,计数器加1;当引用对象的变量被删除、超出作用域或重新赋值时,计数器减1。当计数器为0时,这个对象就不再被使用,Python就会回收它的内存空间,将其归还给操作系统。

然而,引用计数并不是Python内存管理的全部。每当引用计数器无法回收一个对象时,Python会使用垃圾收集器(garbage collector)自动回收不再被引用的对象。垃圾收集器跟踪每个不可达对象,并在需要时释放它们占用的内存空间。

垃圾收集器的机制

Python使用了两个主要的垃圾收集算法:分代回收(generational recycling)和引用计数跟踪(referee tracking)。

分代回收(generational recycling)

在Python中,垃圾通常分为三代:年轻代(young generation)、中间代(middle generation)和老年代(old generation)。新创建的对象通常被分配在年轻代,随着引用计数增加,对象逐渐被转移到中间代和老年代。

因为年轻代的对象通常有较短的生命周期,Python使用了一种称为标记-清除(mark and sweep)的算法,来回收年轻代的垃圾。这个算法会先从根节点开始扫描所有可达对象,标记它们,并将不可达的对象清除。

中间代和老年代的对象通常比较持久,常常是程序中最重要的数据结构。因为这些对象的销毁通常是难以预测的,Python使用了一种称为分代回收(generational recycling)的算法,来针对中间代和老年代的对象进行垃圾回收。这个算法会将内存划分为若干个区域,每个区域代表一代。当一个对象经过若干次垃圾回收后,若仍然存在,就会被转移到下一代。

引用计数跟踪(referee tracking)

除了分代回收算法外,Python还使用引用计数跟踪(referee tracking)算法来辅助进行垃圾回收。这个算法会跟踪对象间的引用关系,并在对象的引用计数归零时进行清理。具体而言,如果一个对象被另一个对象引用,那么它的引用计数就加1;当引用变量指向一个新的对象、被删除或超出作用域时,引用计数器就减1。当引用计数器为0时,Python就会回收对象占用的内存空间。

垃圾收集器的性能调优

通过调整Python中的垃圾收集器,可以提升Python程序的性能。以下是一些可以优化垃圾收集器的方法:

  • 调整阈值:可以使用sys.setrecursionlimit()函数调整分代回收的阈值。这个函数可以设置Python程序的最大递归深度,从而影响分代回收算法的执行次数。默认情况下,Python为年轻代设置了阈值为700,为老年代设置了阈值为10,以平衡性能和稳定性考虑。但是,当需要提高程序的性能时,可以考虑适当增加阈值,使算法执行得更少而更有效率。
  • 安装更快的垃圾收集器:Python中附带了两个垃圾收集器:标记-清除(mark and sweep)和分代回收(generational recycling)。其中,分代回收是Python默认的垃圾收集器,但是这个算法有一定性能问题。因此,可以考虑使用一些其他的垃圾收集器,如追踪垃圾(tracking garbage)或增量式垃圾收集(incremental garbage collection),来提高程序的性能。
  • 编写避免内存泄漏的代码:内存泄漏是指程序在运行时错误地将一些已经释放的内存保留下来,导致系统内存占用量不断增加。解决内存泄漏的方法有很多,比如使用编写稳定的代码,及时释放变量,使用with语句,避免循环引用等。这些方法可以减少Python的内存占用,从而提升程序的性能。
总结

Python的垃圾收集器是自动化的,使用了引用计数器和垃圾回收器。Python使用了分代回收算法和引用计数跟踪算法,在必要时回收不再使用的内存空间。通过调整垃圾收集器、安装更快的垃圾收集器或编写避免内存泄漏的代码,可以提高Python程序的性能。