我的Python学习笔记--内存管理和垃圾回收

不管何种语言,程序运行中都会耗费很多资源,如果有些应用完成以后,资源还不释放,运行性能就会越来越低,甚至发生OOM(out of memery)问题
无论何种垃圾收集机制, 一般都是两阶段: 垃圾检测和垃圾回收.
Python的垃圾回收机制:

  • 引用计数
  • 标记清除
  • 分代回收
引用计数

Python中,主要依靠GC(garbage collector)模块的引用计数技术来进行垃圾回收。
  所谓引用计数,就是考虑到Python中变量的本质不是内存中一块存储数据的区域,而是对一块内存数据区域的引用。所以python可以给所有的对象(内存中的区域)维护一个引用计数的属性,在一个引用被创建或复制的时候,让python,把相关对象的引用计数+1;相反当引用被销毁的时候就把相关对象的引用计数-1。当对象的引用计数减到0时,自然就可以认为整个python中不会再有变量引用这个对象,所以就可以把这个对象所占据的内存空间释放出来了。
  通过sys.getrefcount(), 可以查看该内存地址是否被引用,一般至少会从2开始计数,因为getrefcount()会临时指向此内存地址,引用计数为getrefcount()-1

import sys
a = 'esorta'
print(a)
print(sys.getrefcount('esorta'))# 获取引用计数,实际要减一次
print(sys.getrefcount('shshsh'))# 比a少一次引用,没有变量引用

得到输出

esorta
4
3
  • 初始引用计数并不是1,是因为内部又做了点手脚。当引用计数为0时,进行垃圾回收。
  • python中所有的东西都是对象
  • a = “esorta” 并不是将”esorta”这个字符串赋值赋值给a变量,而是a变量暂时引用指向了“esorta”这个字符串对象
    print(a)表示的是找到这个字符串对象的地址,并将这个地址的值给输出出来
循环引用
a = []
b = []
a.append(b)
b.append(a)

像以上这种循环引用,他们的引用计数都为1,但是显然需要被回收

这里就引出了标记清除

>  针对循环引用这个问题,比如有两个对象互相引用了对方,当外界没有对他们有任何引用,也就是说他们各自的引用计数都只有1的时候,如果可以识别出这个循环引用,把它们属于循环的计数减掉的话,就可以看到他们的真实引用计数了。基于这样一种考虑,有一种方法,比如从对象A出发,沿着引用寻找到对象B,把对象B的引用计数减去1;然后沿着B对A的引用回到A,把A的引用计数减1,这样就可以把这层循环引用关系给去掉了。
>  不过这么做还有一个考虑不周的地方。假如A对B的引用是单向的, 在到达B之前我不知道B是否也引用了A,这样子先给B减1的话就会使得B称为不可达的对象了。为了解决这个问题,python中常常把内存块一分为二,将一部分用于保存真的引用计数,另一部分拿来做为一个引用计数的副本,在这个副本上做一些实验。比如在副本中维护两张链表,一张里面放不可被回收的对象合集,另一张里面放被标记为可以被回收(计数经过上面所说的操作减为0)的对象,然后再到后者中找一些被前者表中一些对象直接或间接单向引用的对象,把这些移动到前面的表里面。这样就可以让不应该被回收的对象不会被回收,应该被回收的对象都被回收了。

简单来说就是创建副本-使用副本验证是否循环使用,这样就会正确的进行回收了

分代回收

分代回收策略着眼于提升垃圾回收的效率。研究表明,任何语言,任何环境的编程中,对于变量在内存中的创建/销毁,总有频繁和不那么频繁的。比如任何程序中总有生命周期是全局的、部分的变量。

  • Python将所有的对象分为0,1,2三代;
  • 所有的新建对象都是0代对象;
  • 当某一代对象经历过垃圾回收,依然存活,就被归入下一代对象。
    这一段看不太懂…先标记一下

采用引用计数方法管理内存的一个缺陷就是循环引用,而Python中GC(garbage collector)模块的一个主要功能就是用来处理循环引用的.

看到了一个有意思的解释,开发商拍地:

每拍一快地,房管局都要登记一下,这个开发商捂地的数量又加一。如果这块地使用完了,开发商捂地的数目减一。这便是引用计数。
如果这块地,一女二嫁,有纠纷。陷入循环死结了。政府就各个击破,请他们喝茶,请他们都退出。这个就是标记-清除。
如果这块地的开发商后台特别强大,捂着就是不开发。地方政府就只能采取一贯的做法,“让后代去解决”。这就是分代回收。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值