首页 > 编程知识 正文

python魔法方法汇总,javascript垃圾回收机制

时间:2023-05-05 05:48:01 阅读:131683 作者:903

#python垃圾回收机制详情

一、概述:

python的GC模块主要使用“参考计数(reference counting )”来跟踪和回收垃圾。 除了参照计数之外,标签清除(现实的花生and sweep )还允许容器(此处的容器值是数组、字典、元组之类的对象() ) ) ) ) ) )

二、垃圾回收三种机制

1、引用计数

在Python中,大多数对象的生命周期由对象的引用计数来管理,广义上既是垃圾回收机制,也是最直观、最简单的垃圾回收机制。

原理:当对象创建或复制引用时,对象的引用数增加1,而当对象的引用被放弃时,对象的引用数减少1。 当对象的引用计数减少到0时,表示该对象已经不被任何人使用,并且可以释放正在使用的内存。

每次分配和释放内存时,引用计数都需要添加管理引用计数的行为,但与其他主要垃圾回收机制相比,最大的优点之一是实时性,任何内存在对他的引用消失时都会立即回收。 其他垃圾回收机制需要某些特殊条件(内存分配失败)才能回收无效内存。

运行效率问题:引用计数机制维护引用计数带来的附加操作与python运行期间执行的内存分配和释放成比例。 与其他机制(如“标记-清除”、“停止-复制”)相比,这些技术带来的操作基本上只涉及回收的数量,因此是弱点。

引用计数的致命弱点之一是循环引用,而垃圾回收机制不包括引用计数。 这需要一种新方法:清除标记。

2、标记清除

清除标记主要用于解决循环引用问题。 循环引用仅在容器对象内发生。 例如,数组、字典、元组等首先需要为每个容器对象保留两个附加指针,以便将容器对象组合成一个链表,以跟踪对象。 指针指向前后两个容器对象。 这样,如果断开对象的循环参照环,则可以获得两个对象的有效计数。

问题说明:

使用循环引用时,一组对象的引用数不再为0,但实际上并未被外部对象引用。 也就是说,没有人再使用此对象,必须回收此对象占用的内存空间,但每个对象的引用数不是0,因为存在交叉引用。 这是因为这些对象占用的内存不会被释放。 例如以下代码:

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

在上面的第一组中,当未执行del语句时,a、b的引用次数均为2(initappend=2),但执行del后,a、b的引用次数相互减少一个。 A、b嵌入循环参照圈,然后出现标签消去算法开始工作。 找到其一端的a,开始拆下a、b的参照环。 (我们从a出发。 那是因为b有参考。 将b的引用计数减少一个,然后沿着引用到达b。 因为b有对a的引用。 同样,通过减少对a的一个引用,可以完成循环引用对象之间的对象循环的提取。 )去除后发现a。

对于第二组,简单来看,d拿到戒指后引用计数仍为1,但a拿到戒指后为0。 此时的c已经在unreachable的链表中,被判处死刑。 但是此时,根表中还有d,d还引用了c。 如果C被取下的话,世界上就没有正义了。 根链接表的d在参照检查中参照c。 没有了c,d也变凉了,所以c被拉回了根链表。

解剖这两个链表的原因是,当前unreachable中可能存在位于根链表中的对象,直接或间接引用的对象。 无法回收这些对象。 一旦在标记过程中发现了这样的对象,就将其移动到路由表中,标记完成后,unreachable链表中剩下的就是名副其实的垃圾对象。 以下垃圾回收必须限制在unreachable链表中

3、分代回收

背景:分代回收技术是20世纪80年代初发展起来的垃圾回收机制。 研究表明,无论用什么总语言开发,开发什么类型、什么规模的程序,一定比例的内存块生存期短,通常是数百万指令的时间,而剩下的内存块生存期长,程序从一开始就结束

从上述"标记-清除"这样的垃圾回收机制来看,该垃圾回收带来的额外操作实际上与系统内的总存储器块数量相关,回收的存储器块越多,垃圾回收带来的额外操作就越多为了提高垃圾的收集效率,采用了“空间的更换”的战略。

原理:系统线程的所有内存块根据生存时间分为不同的集合,每个集合称为“世代”,垃圾回收的频率随世代生存时间的延长而减少。 也就是说,活着时间越长的对象越不应该是垃圾,而应该减少垃圾的收集频率,测定的标准是该对象通过的垃圾的收集次数越多,该对象活着的时间就越长。

例如:

  当某些内存块M经过了3次垃圾回收的清洗之后还是存活着的时候,就将内存块M划到一个集合A中去,当垃圾收集开始工作时,大多数情况只是针对集合B进行垃圾回收,而对集合A进行垃圾回收要隔相当长一段时间才进行,这就使得垃圾收集机制要处理的内存少了,效率自然就提高了。这个过程中集合B中的某些内存块由于存活时间长会被转移到A中, 当然A中实际上也存在一些垃圾,这些垃圾回收会因为这种分带机制而延迟。 在python中,一共有三代,也即维护3条链表(generation 0, 1, 2)

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

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

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。