前言
一、引用计数器
在python中维护了一个refchain的双向环状链表,这个链表中存储程序创建的所有对象,每种类型的对象中都有一个ob_refcnt引用计数器的值,引用分数+1、-1,最后当饮用计数器变为0时会进行垃圾回收(对象销毁、refchain中移除)
二、分代回收、标记清除
在python中对于那些可以有多个元素组成的对象可能会存在循引用问题,为了解决这个问题python又引入了标记清除和分代回收,在其内部维护了四个链表。
- refchain
- 0代:0代中对象个数达到了700个扫描一次
- 1代:0代扫描10次,则1代扫描一次
- 2代:1代扫描10次,则2代扫描一次
在源码内部当达到各自的阈值时,就会触发扫描链表进行标记清除的动作(有循环则各自-1)
三、python缓存
3.1池(int)
为了避免重复创建和销毁一些常见对象,维护池。
# 启动解释器时,python内部帮我们创建:-5、-4、... 257
v1 = 1 # 内部不会开辟内存,直接去池中获取
v2 = 2 # 内部不会开辟内存,直接去池中获取
v4 = 2。# 内部不开辟内存,直接去池中获取
print(id(v2),id(v4)) # 两个内存地址相同
3.2 free_list (float/list/tuple/dict)
当一个对象的引用计数器为0时,按理说应该回收,内部不会直接回收,而是将对象添加到free_list链表中当缓存。以后再去创建对象时,不会重新开辟内存,而是直接使用free_list。
v1 = 3.14 # 开辟内存,内部存储结构体中定义的那几个值,并存到refchain中。
del v1 # refchain中移除,将对象添加到free_list中(80个),free_list满了则销毁
v9 = 333.33 # 不会重新开辟内存,去free_list中获取对象,对象内部数据初始化,在放到refchain中