当前位置: 首页 > 后端技术 > Python

Python垃圾回收机制

时间:2023-03-26 11:47:14 Python

对象:因为Python中万物皆对象,变量的本质其实是指向对象的指针;例如:a=1实际上是先分配内存(创建对象)来存储数据“1”;那么变量a指向对象(变量a存放的是对象的内存地址)不可变对象:变量相对于对象的指针是不会改变的1.对于同一个值的不可变对象,变量指向同一个object2.只要不可变对象的值发生变化时,变量就会指向重新创建的对象objects2.允许可变对象存储数据变量的值改变而不影响变量的指针。由于Python在运行过程中会用到各种变量,如果对象所占用的内存管理不善,就会导致程序因内存溢出而异常终止。1、引用计数方式Python以引用计数为主,辅以mark-clear和分代回收的策略性引用计数方式:对象每被引用一次,引用计数加一;并且当引用销毁时减一,当引用计数为零时回收内存优点1.高效易实现2.实时性:一旦没有引用,直接释放内存3.对象有确定的循环缺点1.资源消耗:维护引用计数的数量与引用分配成正比2.无法解决循环引用问题2.Mark-ClearMark-ClearPhase1:GCmarksallactiveobjects阶段2:GC回收未被标记的非活动对象。活动检测对象相互引用形成有向图,从根对象开始遍历有向图,将可达或间接可达的对象标记为活动对象,回收其他为非活动对象缺点:占用整个堆内存必须顺序扫描以找到活跃和不活跃的对象PyGC:使用不同的链表来持久化跟踪活跃的对象,每个创建的对象都会被添加到零代链表中;那么“检测循环引用”会按照规则减去相互引用对象的引用计数,将引用计数为0的对象进行回收,剩下的活动对象移到生成列表中。Python什么时候做标记回收过程?PyGCThreshold:当分配的计数值与释放的计数值之差达到设定的阈值时,进行标记回收。在第一代链表中也是按照同样的方法将活动对象移动到第二代链表中。3.分代收集分代收集:如果一个内存对象在Mark过程中发现不是垃圾,短期内变成垃圾的可能性很小。分代收集将那些在多次垃圾收集中没有被标记为垃圾对象的内存对象集中到另一个区域——老区域,即这个区域的内存对象比较老。因为old区域的内存对象在短期内变成垃圾的概率很低,所以可以降低这些区域的垃圾回收频率。相对来说,young区的对象垃圾回收频率应该很高。这提高了垃圾收集的整体性能。PyGC:引用按代回收。一代是一个链表。属于同一代的所有内存块都链接在同一个链表中(共三代);每一代的对象数量是有上限的,每创建一个对象都会被加入到零代中去检查零代是否满了,如果满了就开始垃圾回收。PyGC设计了三个“分代”,通过阈值(时间)和对象数上限(空间)完成“标记-清除”和“分代收集”,这两个GC思路在目的上是差不多的。参考博客1:https://www.jianshu.com/p/1e3...【英文翻译】博客2:https://blog.csdn.net/xiongch...【附源码】