python垃圾回收离职_Python之垃圾回收机制

引用计数

Python 语言默认采用的是 引用计数 的垃圾回收机制。 该算法的原理是:每个对象维护一个 ob_ref 的字段,用来记录该对象当前被引用的次数,每当有新的引用指向该对象是,它的引用计数 ob_ref + 1,每当该对象的引用失效时,计数器 ob_ref - 1,一旦引用计数为 0,该对象立即被回收,对象占用的空间会被释放。它的缺点是需要额外的空间维护引用计数,这个问题是其次的,最主要的问题是它不能解决对象中的 “循环引用” 问题,因此,很多语言比如 java 并没有采用才算法来做垃圾的收集机制。

什么是循环-引用?A 和 B 相互引用而在外部没有引用 A B 中的任何一个,它们的引用计数虽然都为 1,但显然应该被回收:

a = {} # 对象 a 的引用计数为 1

b = {} # 对象 b 的引用计数为 1

a['b'] = b # 对象 b 的引用计数 +1 = 2

b['a'] = a # 对象 a 的引用计数 +1 = 2

del a # a 的 ref -1,=1

def b # b 的 ref -1,=1

事实上,Python 本身能够处理这种情况, 可以显示调用 gc.collect(),来启动垃圾回收。

import os

import psutil

import gc

# 显示当前 python 程序占用的内存大小

def show_memory_info(hint):

pid = os.getpid()

p = psutil.Process(pid)

info = p.memory_full_info()

memory = info.uss / 1024 / 1024

print("{} memory used: {} MB".format(hint, memory))

def func_1():

show_memory_info('initial')

a = [i for i in range(10000000)]

b = [i for i in range(10000000)]

show_memory_info('after a,b created')

a.append(b)

b.append(a)

if __name__ == "__main__":

# func_1()

# show_memory_info('finished')

func_1()

gc.collect()

show_memory_info('finished')

#############输出################

initial memory used: 8.49609375 MB

after a,b created memory used: 783.20703125 MB

finished memory used: 783.20703125 MB

initial memory used: 8.3984375 MB

after a,b created memory used: 783.1796875 MB

finished memory used: 8.73828125 MB

所以,Python 的垃圾回收机制并没有那么弱。

标记-清除

标记清除(Mark-Sweep) 算法是一种基于追踪回收(tracing GC)技术实现的垃圾回收算法。它分为两个阶段:第一个阶段是标记阶段,GC会把所有的活动对象打上标记,第二个阶段是把那些没有标记的对象非活动对象进行回收,那么GC又是如何判断哪些是活动对象哪些是非活动对象呢?

对象时间通过引用(指针)联系在一起,构成一个有向图,对象构成这个有向图的节点,而引用关系构成这个有向图的边。从跟对象(root object)出发,沿着有向边遍历对象,可达的(reachable)对象标记为活动对象,不可达的对象就是要被清除的非活动对象。根对象就是全局变量、调用栈、寄存器。

每次遍历全图,对于 Python 而言是一种巨大的性能浪费。所以,在 Python 的垃圾回收实现中,mark-sweep 使用双向链表维护了一个数据结构,并且只考虑容器类的对象(只有容器类的对象,才有可能才生循环引用)。

缺点:清除非活动的对象前它必须顺序扫描整个堆内存,哪怕只剩下小部分活动对象,也要扫描所有对象。

分代回收

分代回收是一种以空间换时间的操作方式,Python 将内存根据对象的存活时间分为不同的集合,每个集合称为一个代,Python 将内存分为3“代”,分别为年轻代(第0代),中年代(第1代),老年代(第2代),他们对应三个链表,其垃圾回收频率与对象的存活时间的增大而减少。新创建的对象都会被分配到年轻代,年轻代链表的总数达到上限,Python垃圾回收机制就会被触发,把那些可以被回收的对象回收掉,而那些不会被回收的对象就被移到中年代上去,以此类推,老年代中的对象是存活时间最久的对象,甚至是存活于整个系统的生命周期。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值