Python-垃圾回收机制

 一、引用计数器

C源码-结构体
C源码-结构体

1.1、循环双链表

# 环状双向链表-refchain
"""
环状双向链表-refchain:创建的任何对象都会放在refchain链表中
{
    name="huge"
    age=15
    hobby=["篮球","美女","游戏"]
}
内部会创建一个结构体【上一个对象,下一个对象,类型,引用个数】。通用存这四个
{
    name="huge"
    new=name       引用个数:2
}

1.2、数据封装类

data=3.14

内部会创建:

        _ob_next

        _ob_prev

        ob_refcnt=1

        ob_type=float

        ob_fval=3.14

1.3、引用计数器

当python运行程序时,会根据数据类型不同找到对应的结构体,根据结构体中的字段来创建相关的数据,然后将对象添加到refchain双向链表中 

在C原码中,有两个关键的结构体:PyObject、PyVarObject

        PyObject:存储公共的值,每个对象都有

        PyVarObject:存储由多个元素组成时,公共的值

每个对象都有ob_refcnt,默认值1;当其他变量引用时,引用计数器变换。

# 引用

a=99         # ob_refcnt=1

b=a           # ob_refcnt=2

# 删除引用

del b         # b变量删除,b引用对象的计数器-1

 由此当一个对象的引用计数器为0时,表示没有人在使用找个对象,这个对象就是垃圾,垃圾回收。

# 回收

1、对象从refchain链表中移除;2、将对象销毁,内存归还

二、标记清除

 2.1、循环引用问题&交叉感染

v1 = [1, 2, 3]  # v1_refcnt=1
v2 = [4, 5, 6]  # v2_refcnt=1
v1.append(v2)  # v2_refcnt=2
v2.append(v1)  # v1_refcnt=2
del v1  # v1的引用计数器-1  v1_refcnt=1
del v2  # v2的引用计数器-1  v2_refcnt=1
# 此时删除v1,v2,他们的引用计数器=1,不会被清除,就变成了垃圾

 2.2、标记清除

# 为了解决引用计数器循环引用的不足

# 实现:在Python底层中在维护一个链表,专门存放可能存在循环引用的对象(列表list,字典dict,元组tuple,集合set)

# 在某种情况触发,回去扫描可能出问题的链表中的每个元素,检查是否有循环引用,有则双方引用计数器都-1,如果是0,则垃圾回收。

三、分代清除

将可能存在循环应用的对象维护成三个联表:

  •  0代:0代中对象个数达到700个,扫描一次
  • 1代:0代扫描10次,1代扫描一次
  • 2代:1代扫描10次,2代扫描一次

将新加的元素添加到0代中,当新加的元素达到700个,扫描一次,将循环引用的对象引用计数器-1,垃圾回收,不是垃圾的放到1代中,并标记1代,0代扫描了一次;循环十次后才会扫描1代,以此类推。 

四、小结

        在python中维护了一个refchain的双向环状链表,这个链表中存储程序创建的所有对象,每种类型的对象中都有个ob_refcnt引用计数器的值,引用个数 +1、-1,最后当引用计数器变为0时会进行垃圾回收(对象销毁、refchain中移除)。
        但是,在python中对于那些可以有多个元素组成的对象可能会存在循环引用的问题,为了解决这个问题python又引入了标记清除和分代回收,在其内部为了4个链表,
refchain
。2代,10寸
。1代,10次
。0代,700个
在源码内部当达到各自的阈值时,就会触发扫描链表进行标记清除的动作 (有循环则各自-1)。
But,源码内部在上述的流程中提出了优化机制

五、Python中的缓存机制

5.1、池(int)

为了避免重复创建和销毁一些常见对象,维护池

# 启动解释器,Python内部帮我们创建一个池:-5,-4,....,257 v1 = 7 ; 内部不会开辟内存,直接去池中获取

 5.2、Free_list(float、list、tuple、dict)

当一个对象的引用计数器为0时,应当回收;但是内部不会直接回收,而是将对象添加到free_list链表中当缓存。当再次创建对象时不会重新开辟内存,而是直接使用free_list

当free_list存满时,才会销毁

v1=3.14        # 开辟内存,内部存放结构体中定义的值,并存放到refchain中

del v1           # 删除v1,从refchain中移除,将对象放到free_list中缓存,如果free_list存满,则销毁

v9=99.99      # 不会在开辟内存,而是从free_list中获取对象,并将对象重新赋值,存到refchain中

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值