python垃圾回收机制原理

python垃圾回收机制原理#python垃圾回收机制详解一、概述:  python的GC模块主要运用了“引用计数(referencecounting)”来跟踪和回收垃圾。在引用计数的基础上,还可以通过标记清除(markandsweep)解决容器(这里的容器值指的不是docker,而是数组,字典,元组这样的对象)对象可能产生的循环引用的问题。通过“分代回收(generationcollection)”以空间换取时间来进一步提高垃圾回收的效率。二、垃圾回收三种机制  1、引用计数  在Python中,大多数对象的生命周

大家好,又见面了,我是你们的朋友全栈君。

#python垃圾回收机制详解
一、概述:
  python的GC模块主要运用了“引用计数(reference counting)”来跟踪和回收垃圾。在引用计数的基础上,还可以通过标记清除(mark and sweep)解决容器(这里的容器值指的不是docker,而是数组,字典,元组这样的对象)对象可能产生的循环引用的问题。通过“分代回收(generation collection)”以空间换取时间来进一步提高垃圾回收的效率。
二、垃圾回收三种机制
  1、引用计数
  在Python中,大多数对象的生命周期都是通过对象的引用计数来管理的, 广义上讲,它也是一种垃圾回收机制,而且是一种最直观最简单的垃圾回收机制。
  原理:当一个对象被创建引用或者被复制的时候,对象的引用计数会加一,当一个对象的引用被销毁时,对象的引用计数会减一,当对象的引用计数减为0的时候,就意味着对象已经没有被任何人使用了,可以将其所占用的内存释放了。
  虽然引用计数必须在每次分配和释放内存的时候加入管理引用计数的这个动作,然而与其他主流垃圾收集机制相比, 最大的一个优点是实时性, 及任何内存,一旦没有指向他的引用,就会立即被回收,其他的垃圾回收机制必须在某种特殊条件下(内存分配失败)才能进行无效内存的回收。
  执行效率问题: 引用计数机制带来的维护引用计数带来的额外操作与python运行中所运行的内存分配和释放,引用赋值的次数是成正比的。相比其他机制,比如“标记-清除”,“停止-复制”,是一个弱点,因为这些技术所带来的操作基本上只是与待回收的数量有关。
引用计数还存在的一个致命的弱点是循环引用,这使得垃圾回收机制从来没有将引用计数包含在内。这就需要我们用新的方法了, 即标记清除。
2、标记清除
标记清除主要是用来解决循环引用产生的问题的,循环引用只会在容器对象中才会产生,比如数组、字典、元组等,首先是为了追踪对象,需要每个容器对象维护两个额外的指针,用来将容器对象组成一个链表,指针分别指向前后两个容器对象,这样就可以将对象的循环引用环摘除,就可以得出两个对象的有效计数。
问题说明:
  循环引用可以使得一组对象的引用计数不是0, 然而这些对象实际上并没有被外部对象所引用,这就意味着不会再有人使用这组对象, 应该回收这组对象所占用的内存空间,然而由于相互引用的存在,每一个对象的引用计数不为0,因为这些对象所占用的内存永远不会被释放。比如下面的代码:

a = [1, 2]
b = [3, 4]
a.append(b)
b.append(a)
del a
del b
# B
c = [3, 5]
d = [2, 4]
c.append(d)
d.append(c)
del c

现在就这个做一下解释,这是个集中营, 一个是root object(链表),另一个是unreachable链表。
对于上面的第一组, 在未执行del语句的时候,a,b的引用计数都是2(init + append= 2),但是在DEL执行完毕之后,a,b的引用次数互相减一。a,b陷入循环引用的圈子中,然后标记清除算法开始出来做事,找到其中一端a,开始拆a,b的引用环(我们从a出发,因为它对B有一个引用,则将B的引用计数减一,然后顺着引用到达B,因为B有一个对A的引用,同样将A的引用减一,这样就完成了循环引用对象之间的对象环摘除), 去掉以后发现a,b循环引用变成了0,所以a,b就被处理到unreachable链表中直接被做掉。
对于第二组,简单一看d取环后引用计数还是1,但是a取环后就是0了这时的c已经进入了unreachable的链表中,被判了死刑,但是此时在root表中还有d,d还在引用着c,如果c被搞掉,世界就没有了正义。root链表中的d会被引用检测引用了c,如果c没了,那么d也就凉凉了,所以c又拉回到了root链表中。
解剖这两个链表的原因是现在在unreachable中可能存在被root链表中的对象,直接或者间接引用的对象,这些对象是不能被回收的,一旦在标记的过程中,发现这样的对象就将其移动到root链表中,完成标记后,unreachable链表中剩下的就是名副其实的垃圾对象了,接下来垃圾回收只需要限制在unreachable链表中即可。
3、分代回收
在这里插入图片描述
背景:分代回收技术是上个世纪80年代初发展起来的一种垃圾回收机制,经过研究表明:无论使用何总语言开发无论开发的是何种类型,何种规模的程序,都存在这样一点相同之处, 即:一定比例的内存块的生存周期都比较短,通常是几百万条指令的时间,然而剩下的内存块,生存周期比较长,甚至会从一开始直到程序结束。
从前面的“标记-清除”这样的垃圾回收机制来看,这种垃圾收集机制带来的额外操作实际上与系统中总的内存块的数量是相关的,当要回收的内存块越多时,垃圾检测带来的额外操作就越多,而垃圾回收所带来的额外操作就越少,反值则相反。为了提高垃圾的收集效率,采用“空间换时间”的策略。
原理: 将系统红所有内存块根据其存活时间划分为不同的集合每一个集合就称为一个“代”,垃圾收集的频率随着代的存活时间的增大而减少。也即,活的时间越长的对象就越不可能是垃圾,就应该减少对它的垃圾收集频率,衡量的标准就是这个对象经过的垃圾收集次数越多,该对象存活的时间就越长。
例如:
  当某些内存块M经过了3次垃圾回收的清洗之后还是存活着的时候,就将内存块M划到一个集合A中去,当垃圾收集开始工作时,大多数情况只是针对集合B进行垃圾回收,而对集合A进行垃圾回收要隔相当长一段时间才进行,这就使得垃圾收集机制要处理的内存少了,效率自然就提高了。这个过程中集合B中的某些内存块由于存活时间长会被转移到A中, 当然A中实际上也存在一些垃圾,这些垃圾回收会因为这种分带机制而延迟。 在python中,一共有三代,也即维护3条链表(generation 0, 1, 2)

  • 0代表幼儿对象。
  • 1代表青年对象。
  • 2代表老年对象。

依据弱代假说(越年轻的越容易死掉)
新生的对象放在0代,对象在0代的第一次垃圾收集机制中活了过来, 那么久将其放到第1代里面了,同理,可能会被放到第2代。GC每代垃圾回收处罚的阈值可以自己设置(目前我不知道怎么设置/苦笑)。
这些就是目前的python的垃圾回收机制了。
下面的是 内存池以及调优手段:
内存池:
python的内存机制呈现金字塔形状,-1, -2层主要由操作系统进行操作。
第0层是C中的malloc, free等内存分配和释放函数进行操作
第一层和第二层是内存池,有python借口函数,PyMem_Malloc函数实现,当对象小于256K时候由该层直接分配内存,
第三层是最上层,也即我们对python对象的直接操作。
调优手段:
1、手动垃圾回收
2、避免循环运用
3、提高垃圾回收阈值

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/149507.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 可以识别图片上的文字的小程序

    可以识别图片上的文字的小程序微信上的小程序相信大家都不陌生,近年来,微信小程序从“跳一跳”之后,越发火了。由于小程序的出现,微信上的功能也逐渐增加了,今天就给大家介绍一个小程序,比较实用,它可以快速识别图片上的文字,这个小程序呢就叫“迅捷文字识别”。这是一个比较智能的文字识别的小程序,它可以将识别出来的字汉英互译,还可以直接拍照翻译,接下来就给大家介绍一下这个小程序的操作方法。1.首先,我们现在微信上找到这个程序,点…

    2022年5月29日
    41
  • pandas at loc_pandas str

    pandas at loc_pandas strpandas中.loc和.iloc以及.at和.iat的区别显示索引和隐式索引显示索引和隐式索引importpandasaspddf=pd.DataFrame({‘姓名’:[‘张三’,‘李四’,‘王五’],‘成绩’:[85,59,76]})#传入冒号‘:’,表示所有行或者列#显示索引:loc,第一个参数为index切片,第二个为columnsdf.loc[2] #index为…

    2022年8月30日
    1
  • 用MDK生成bin文件的步骤及方法

    用MDK生成bin文件的步骤及方法1用MDK生成bin文件Embest徐良平在RVMDK中,默认情况下生成*.hex的可执行文件,但是当我们要生成*.bin的可执行文件时怎么办呢?答案是可以使用RVCT的fromelf.exe工具进行转换。也就是说首先将源文件编译链接成*.axf的文件,然后使用fromelf.exe工具将*.axf格式的文件转换成*.bin格式的文件。下面将具体

    2022年10月20日
    0
  • [EE261学习笔记] 4.常用的几个傅里叶变换相关公式

    [EE261学习笔记] 4.常用的几个傅里叶变换相关公式在本文开始前,需要说明一点,以下推导出的各项公式,只是为了实际计算中方便,并不都有其对应的物理意义。首先,我们写出符号f−(t)=f(−t)f−(t)=f(−t)f^-(t)=f(-t),显然,对于奇函数而言,f−=−ff−=−ff^-=-f;对于偶函数而言,f−=ff−=ff^-=f。根据前文傅里叶变换推导,我们知道…

    2022年7月17日
    11
  • UART接口简介_uart接口速度

    UART接口简介_uart接口速度UART即通用异步收发传输器(UniversalAsynchronousReceiver/Transmitter),它是一种串行通信的物理接口形式。它将要传输的资料在串行通信与并行通信之间加以转换。作为把并行输入信号转成串行输出信号的芯片,UART通常被集成于其他通讯接口的连结上。一、UART硬件连接UART有4个pin(VCC,GND,RX,TX),用的TTL电平,低电平为0(0V),高电平为1(3.3V或以上)。如下图:引脚介绍:…

    2022年9月14日
    0
  • java反射 getMethod_JAVA 反射 getMethod() 和 invoke() 具体应用[通俗易懂]

    java反射 getMethod_JAVA 反射 getMethod() 和 invoke() 具体应用[通俗易懂]最近有一个有很多输入框的JSP页面,在页面上inputname都是有规律的命名,在提交到后台时,通过JAVA反射机制可以减少不少代码量,特此记录一下实现!JSP页面大概如下:全程陪诊后续价格:V2普通会员元V2银牌会员元V2金牌会员元V2钻石会员元V3普通会员元V3直通会员元V3专护会员元V3专家会员元全程陪检后续价格:V2普通会员元V2银牌会员元V2金牌会员元V2钻石…

    2022年9月23日
    0

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号