python垃圾回收

python的垃圾回收机制主要是引用计算,同时辅助使用标记-清除解决循环应用,分代回收可以减少垃圾回收扫描的频率。

  • 引用计数
      python默认的垃圾回收机制就是”引用计数”,每个对象维护一个引用计数,当新的引用指向该对象时,引用计数加1,当一个引用被销毁时减1,一旦引用计数为0,该对象立即被回收,所占用的内存将被释放。它的主要问题是不能解决”循环引用”问题。循环引用使得对象一直驻留在内存中,造成内存泄漏。为了解决循环引用问题,引入了标记清除和分代回收机制。
  • 标记清除
      标记-清除是一种基于追踪回收技术实现的垃圾回收算法,对象之间通过引用连在一起,构成一个有向图,对象构成有向图的节点,引用关系是边。从根对象出发,沿着有向边遍历对象,可达的对象标记为有用的对象,不可达的对象是要清除的对象。所谓根对象就是一些全局引用对象和函数栈中的引用,这些引用所引用的对象是不可删除的。
      标记清除算法作为python的辅助垃圾收集机制主要处理的是容器,因为字符串和数值对象不可能造成循环引用。
  • 分代回收
      分代回收是一种以空间换时间的操作方式,Python将内存根据对象的存活时间划分为不同的集合,每个集合称为一个代,Python将内存分为了3“代”,分别为年轻代(第0代)、中年代(第1代)、老年代(第2代),他们对应的是3个链表,它们的垃圾收集频率与对象的存活时间的增大而减小。新创建的对象都会分配在年轻代,年轻代链表的总数达到上限时,Python垃圾收集机制就会被触发,把那些可以被回收的对象回收掉,而那些不会回收的对象就会被移到中年代去,依此类推,老年代中的对象是存活时间最久的对象,甚至是存活于整个系统的生命周期内。同时,分代回收是建立在标记清除技术基础之上。
      分代回收同样作为Python的辅助垃圾收集技术处理那些容器对象。

垃圾回收时,python不能进行其它的任务。频繁的垃圾回收会大大降低python的效率。如果内存中的对象不多,就没有必要总启动垃圾回收。所以,python只会在特定的条件下,自动启动垃圾回收。当python运行时,会记录其中分配对象和取消分配对象的次数。当两者差值高于某个阈值,垃圾回收才会启动。垃圾回收时一定会扫描所有的0代对象,0代经过一定次数的垃圾回收,就会启动对0代和1代的扫描清理,当1代也经历一定次数的垃圾回收后, 就会启动对0代1代和2代所有对象的扫描。
gc.get_threshold()返回(700, 10, 10)表示700即是垃圾回收启动的阈值,返回的两个10,每10次0代垃圾回收,会配合1次1代的垃圾回收;而每10次1代的垃圾回收,才会有1次的2代垃圾回收。