【Python | 内存管理-内存的回收机制】


一、引用机制

  • python中每个对象都维护一个引用计数 ob_ref 字段
  • 当有新的引用指向该对象的时候,引用计数+1
  • 当有无效引用发生的时候,引用计数-1
  • 当引用计数为0时,销毁对象

引用机制的优点:

  • 简单
  • 实时性

引用机制的缺点:

  • 维护引用计数消耗资源
  • 循环引用时,无法回收
>>> from sys import getrefcount
>>> a = 1000
>>> getrefcount(a)
2

只引用赋值给了a,但是引用计数为2是因为=>在使用getrefcount的时候也会有一次临时引用,
获取到a的时候这个临时引用就销毁了

>>> b = a
>>> getrefcount(a)
3
>>> c = []
>>> c.append(b)
>>> getrefcount(a)
4

getrefcount => 得到的引用计数会比实际多1次

  • 循环引用
    • 根据引用计数的规律,出现循环引用的情况=> 引用计数不为0 => 无法通过引用计数来释放内存
      => 会造成内存泄漏
      • 内存泄漏:有一部分内存被占用无法释放,进程也无法访问
        内存泄漏可能造成内存溢出
      • 内存溢出(oom => out of memory):内存不够,程序需要的内存大于系统空闲内存
>>> x = [2]
>>> y = [3]
>>> x.append(y)
>>> y.append(x)
>>> getrefcount(x)
3
>>> getrefcount(y)
3
>>> del x
>>> del y

img

二、垃圾回收

  • 回收原则:当python的某个对象的引用计数降为0时,可以被垃圾回收

  • gc(garbage collection)机制

    • 分代回收
    • 标记清除
>>> x = [2]
>>> y = [3]
>>> x.append(y)
>>> y.append(x)
>>> del x
>>> del y
>>> gc.collect()
2

1. 分代回收

启动垃圾回收的时候确定哪些是扫描对象的

2. 标记清除

主要解决循环引用 => 清除非活动的标记


三、内存池

  • 预先创建好一个小整型数池 [-5,256]
>>> a = 3
>>> getrefcount(a)
55
>>> a = 1
>>> getrefcount(a)
874
>>> a = 300
>>> getrefcount(a)
2
>>> 

在这个小整型池里的数就不会再重复创建了,直接引用池子里已经创建好的

  • 字符串驻留区
    • 单个字符创建之后都会放在驻留区
    • 多个字符创建之后如果包含特殊字符就不会放在字符串驻留区,如果没有特殊字符就会存放到驻留区
>>> str1 = "abcxyz"
>>> str2 = "abcxyz"
>>> id(str1)
139668314459528
>>> id(str2)
139668314459528
>>> str1 = "xyz abc"
>>> str2 = "xyz abc"
>>> id(str1)
139668313995952
>>> id(str2)
139668313995896

总结

python的内存管理:
以引用计数为主,
分代回收、标记清除为辅的垃圾回收方式。

以及对小整数型进行缓存和简单字符串驻留的内存池机制

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值