【Python】内存管理机制

Python的内存管理机制:

  • 1)引用计数
  • 2)垃圾回收
  • 3)内存池

1、引用计数

当一个Python对象被引用时,其引用计数增加1,当其不再被变量引用时,其引用计数减1,当对象的引用计数为0时,对象被删除。

引用计数是一种非常高效的内存管理机制

2、垃圾回收

垃圾回收机制:

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

描述垃圾回收之前先引入一个概念:refchain双向环状链表。这个链表的作用很强大,python内部会维护一个这样的链表,当python程序中一旦创建对象,都会把创建的对象添加到refchain中,这个链表保存了所有创建的对象,并且每个对象都包含了上下对象的指针、引用计数和对象的类型。

引用计数:

在refchain双向环状链表中所有的对象内部都有一个自己的引用计数器,表示该对象被引用的次数。当一个python的对象被变量引用时,引用计数+1,不在被变量引用时,引用计数-1,当对象的引用计数为0时,对象就会被当做垃圾回收掉(对象从refchain链表中摘除,释放内存(不考虑缓存等特殊情况))

但引用计数会存在一个问题:循环引用

  • 循环引用:两个对象相互引用。
  • 场景:如果没有变量去引用两个对象,并且两个对象存在循环引用,那么这两个对象的引用计数不为0,导致它们永远不会被使用或者销毁
  • 存在循环引用的对象:
    1. 列表
    2. 元组
    3. 字典
    4. 集合
    5. 自定义类等能进行数据嵌套的类型
  • 后果:项目中如果存在大量这种对象,就会导致内存一直被消耗,直到内存被耗尽,程序崩溃;当重启系统的时候内存又会空闲很多。
  • 解决办法:引入标记清除和分带回收
标记清除:

创建特殊链表专门用于保存列表、元组、字典、集合、自定义类等对象,之后再去检查这个链表中的对象是否存在循环引用,如果存在则让双发的引用计数-1,当引用计数为0时,则是垃圾,进行回收。否则不是垃圾。

分带回收:(阈值)

对标记清除的链表进行优化,将那些可能存在循环引用的对象拆分到3个链表中,链表分为:0/1/2三代,每代都可以存储对象和阈值,当达到阈值时,就会对相应的链表中的每个对象做一次扫描。扫描的结果是:如果对象存在循环引用,则对象的引用计数都-1,为0的话则视为垃圾回收,如果不是垃圾,则将对象放入下一代链表中。

0/1/2三代的扫描时机和阈值:

  • 0代:当0代链表的对象个数达到700个时会扫描一次
  • 1代:当0代链表扫描10次时扫描一次
  • 2代:当1代链表扫描10次时扫描一次

3、python缓存机制

可以从上文了解到如果对象的引用计数为0时,就会被销毁并释放内存。实际并不是这样子,因为频繁地创建和销毁对象的代价很大并且会影响程序的执行效率。为了解决这个问题,python中引入了 缓存机制

例如:引用计数为0时,并不会真正的销毁对象,而是将它放到一个链表中,之后再创建对象时不会再重新开辟新的内存,而是在这个链表中将之前的对象进行重新赋值来使用

不同的数据类型,有不同的缓存机制。

3.1 池(int)

为了避免重复创建和销毁一些常见的对象,池中会初始化[-5~257]范围的整型对象,创建这些对象时,直接从池中获取对象并不会重新开辟新的内存

3.2 free_list(float、list、tuple、dict)

当一个对象的引用计数为0时,按理说应该回收,但内部不会回收,而是将对象添加到free_list链表中当缓存,以后再创建对象对应的类型时,不再开辟新内存,而是直接从free_list中获取

数据类型free_list缓存对象个数
float100
tuple20
dict80
list80

对于tuple,存储的20个元组对象特点为:第一个为空元组、第二个为元素只有一个的元组,接下来以此类推…

4、调优手段

  1. 手动垃圾回收
  2. 避免循环应用
  3. 调高垃圾回收阈值
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值