分代回收python,python的回收机制是什么

  分代回收python,python的回收机制是什么

  055-79000可会员分享,在线阅读。关于《Python垃圾回收机制简介》的更多信息,请在人人网上搜索。

  1.众所周知,Py tho n是一种面向对象的语言。在Py tho n的世界里,一切都是对象。所以,所有变量的本质只是对对象的引导。Python在运行的时候,会不断地创建各种变量,但是这些变量必须存储在内存中。随着程序的运行,变量数量增加,占用空间变大。如果变量占用的内存空间管理不当,就会出现内存输出。程序非正常结束的概率很大。因此,高效合理地管理内存空间就显得尤为重要。那么Python是如何解决这个问题的呢?其实很简单。回收不能再用的内存。这就是为什么程序员需要像C语言一样手动释放内存。问题是如何确定哪个内存将不再被使用。

  2.啊?这就是我们今天要讲的垃圾收集。目前,垃圾收集有三种常见的解决方案:引用计数、标记移除和逐代回收。计数也是最直观简单的垃圾收集技术。在Python中,大多数对象的生命周期由对象的引用数量来管理。原理很简单。为每个对象维护ref中的字段,以记录该对象被引用的次数。每次创建或引用一个对象时,该对象的引用次数增加,当放弃该对象的引用时,该对象的引用次数增加。也就是说,如果在未来的程序运行中不再使用该对象,那么就可以释放被占用的空间。看看下面的例子。imp .

  3.ort osirriport psutil ff Print 3程序占用的内存大小def Print _ Memory _ INFO(NAOE):PID=OS . getpid)IP-psutil . process PID 1024 Memory=info.liss/mbprintcssusd审计dMB/%(inamemmcry) #测试函数def f00) 3360iprint

  4、iinrange(length)prinit _ in nery _ info)foo end)foo)lprint _ mgmopy _ info)mairend)#输出为foostartused6mbfoood。从打印结果可以看出,创建列表后,程序占用的内存空间增加到了55 MB。调用函数foo后,内存消耗恢复正常。这是因为用函数foo创建的列表变量是一个局部变量,它的范围是。

  5.在当前函数内,函数执行后,对局部变量的引用将被自动放弃。也就是说,它的引用次数为零,使用的内存空间也被回收。为了验证我们的想法,我们稍微修改了函数foo。代码如下。def 00(:pr 1nt memory _ itif)foostart)length=1000 * 1000 list-I for I in width安歌)ln juth) print _ in memory _ iin返回list foo输出结果调用staPt used e MBfooend used EE MBfoo函数后,消耗的内存仍在foo内部,

  6.最终使用的55 MB也可以在稍加修改后放置。主要原因是使用函数后,可能会保留对列表的引用,对象可能会继续使用,但垃圾回收不会恢复对象。那么,什么时候对象的引用数量会增加呢?在下面四种情况下,一个对象的引用次数会增加一:对象已经创建了吗?对象被引用(count=num?对象是作为参数在函数内部传递的吗?就像将对象作为单个元素添加到容器中一样,有四种类型的对象,它们的引用时间会减少一次。的别名会被显式销毁吗?该对象的别名将被授予新对象。(num=30)?对象是否远离其作用域(函数局部变量)?从容器中删除一个对象或者销毁容器的引用计数看起来非常简单,其实现也不复杂。

  7.因为在一个字段中节省对象被引用的次数就足够了,不就说明这个算法没有缺点了吗?否则,我们知道必须回收引用时间为零的对象所占用的内存空间。引用次数不为零的对象不能回收吗?看看下面的例子。只修改了函数foo,其余不变。def f00c):IPN int _ in 5 mory _ infofoestart)length=105 * i00 list _ a=iforinrange(length)list _ b=iforinrarararange

  8,d(list_a,)print_inernory_inf foo ) ret

  urn list material # output result foo start用了6mq foo end用了9m6 main end用了93mb和list_b,foo函数我们可以看到在函数foo中生成了两个list _ alist _ a,然后将这两个list分别添加到另一个中。从结果中可以看出,即使号码结束后,其占用的内存空间仍然没有释放。这是因为和list_b没有被任何外部对象引用,但是由于它们之间的交叉引用,每个对象的引用计数都不为零,导致它们所占用的空间永远不会被回收的尴尬局面。这个缺点是致命的。因为。

  9.为了解决交叉引用的问题,P ython Bow I包含了标签清除算法和生成回收算法。很明显,所有可以包含其他对象引用的容器对象都可能引起交叉引用问题,标记清除算法就是为了解决交叉引用问题。标记算法是基于对象可达性分析的回收算法,分为标记和清除两步。标记阶段,标记所有活动对象,在清除阶段回收所有未标记的对象。所以现在问题变成了,GC如何确定哪些对象是活动的?实际上,GC会从根节点开始,直接或间接连接到根节点的对象会被标记为活动对象(这个对象可以到达),然后在回收阶段清除未标记的对象(不可到达的对象)。前述根节点可以是全局变量。

  10、或调用堆栈。标记算法主要用于处理一些容器对象。虽然这种方法可以完全避免killing或missing,但是GC时必须扫描整个堆内存,即使只需要回收少数不可及的对象,也需要扫描所有对象。这是对性能的巨大浪费。逐代回收会导致性能损失,因为需要扫描整个堆中的所有对象,可回收的对象数量越少,性能损失就越大。因此,P ython引入了世代回收算法,将生存时间不同的对象划分到不同的内存区域,有三个世代,即0代、1代和2代。生成的对象是第0代,经过一次垃圾回收后,存活的对象将升级到第1代,以此类推,第2代中的对象是存活时间最长的对象。那么垃圾收集算法什么时候会被触发呢?事实上,有了这个程序。

  11.运营会开一代。不断地创建新对象,同时又因为引用计数为零而销毁了大部分对象。Pyth on将跟踪这些对象。由于程序中交叉引用和长寿命对象的存在,新生成的对象数量将大于收集的对象数量。一旦两者之差达到一定阈值,就会启动垃圾收集机制。用标记清除算法清除死的物体,同时把活的物体移到等等。当它们之间的差异再次达到阈值时,垃圾收集机制被触发,活对象被移动到第二代。这样,通过设置不同代的不同阈值,可以在不同代使用不同的时间间隔进行垃圾收集,从而追求最大的性能。其实所有的程序都有一个类似的现象,就是大部分对象的生命周期都相当短。

  12.只有少数对象的生命周期很长,甚至是内存驻留,从程序开始一直持续到程序结束。通过世代回收算法,对不同的区域采用不同的回收频率,节省了大量的计算,提高了Py tho n的性能,除了上面提到的当差值达到一定阈值时会触发垃圾收集,我们还可以调用gc.collect()来触发垃圾收集,最后在程序退出时进行垃圾收集。本文总结了P ython的垃圾收集机制。垃圾收集是P ython的一个功能,不需要程序员手动管理内存。其中引用计数法最简单直接,但是需要维护一个字段,对交叉引用无能为力。标记算法主要用于解决引用计数的交叉引用问题。这种算法的缺点是需要扫描整个堆中的所有对象,浪费了性能。世代回收算法的引入,完美解决了标签清除算法需要扫描整个堆对象所带来的性能浪费问题。该算法也基于标记清除。最后,我们可以通过gc.collectO手动触发GC的操作

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: