python 垃圾回收
【第1题】 Pythonn内存管理以及垃圾回收机制 - 武沛齐 - 博客园 (cnblogs.com)
https://www.bilibili.com/video/BV1F54114761/
元祖
总结:
Python每个对象创建时,都加入了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个元素。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)