【第1题】 Pythonn内存管理以及垃圾回收机制 - 武沛齐 - 博客园 (cnblogs.com)
https://www.bilibili.com/video/BV1F54114761/
元祖
总结:
为了回收内存,每个对象都加入了refchain双向环向链表,对象被引用+1,del掉-1,等于0内存就被回收,这个叫引用计数器ob_refcnt;但是像列表这种互相引用的,会出现循环引用问题。导致计数器不为0的情况,内存无法回收。所以出现了标记清除。
再维护一个链表,把可能存在循环引用(list,tuple,dict,set)的放入这个链表里,集中管理。某种情况下,触发扫描,然后是引用计数器那一套。但是扫描比较耗时,所以把标记清除一个链表拆分成3个,谓之曰分代回收。
不需要标记清除的链表,而是再维护三个链表0代,1代,2代。这个三个链表触发机制是,先0代,对象存refchain的时候,也放一份到0代里,当0代里的对象数量达到700及以上时,出发内存回收。0代执行10次才会执行一次1代。1代执行10次才会执行一次2代。
以上就是引用计数器,标记清除和分代回收的概念。引用计数器是最核心和根本的,而分代回收是标记清除的具体实现和优化。所以最后维护了4个链表,refchain、0代、1代和2代。这里强调一下,refchain放的是所有对象。
进一步优化就是后面的缓存机制:池和free_list。都是为了避免常用对象重复创建和销毁的。
顺带提一下,对象底层实现:Python中所有类型创建对象时,底层都是与PyObject和PyVarObject结构体实现,一般情况下由单个元素组成对象内部会使用PyObject结构体(float)、由多个元素组成的对象内部会使用PyVarObject结构体(str/int/list/dict/tuple/set/自定义类),因为由多个元素组成的话是需要为其维护一个 ob_size(内部元素个数)。
- 2个结构体
- PyObject,此结构体中包含3个元素。
- _PyObject_HEAD_EXTRA,用于构造双向链表。
- ob_refcnt,引用计数器。
- *ob_type,数据类型。
- PyVarObject,次结构体中包含4个元素(ob_base中包含3个元素)
- ob_base,PyObject结构体对象,即:包含PyObject结构体中的三个元素。
- ob_size,内部元素个数。
- PyObject,此结构体中包含3个元素。
标签:python,元素,ob,回收,链表,PyObject,垃圾,引用 From: https://www.cnblogs.com/daizichuan/p/17643244.html