前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >python 的内存管理与垃圾收集

python 的内存管理与垃圾收集

作者头像
用户3147702
发布2022-06-27 12:56:38
3510
发布2022-06-27 12:56:38
举报
文章被收录于专栏:小脑斧科技博客

1. 概述

我们知道,Python 不需要提前声明变量,也无需指定其类型,变量的类型和内存占用都是运行时决定的。 赋值时,解释器会根据语法和右侧的操作数来决定新对象的类型。 在对象创建后,一个该对象的应用会被赋值给左侧的变量。 Python 程序的内存分配和释放都是解释器进行操作的,不需要程序员手动处理。

2. 引用计数

Python 使用了引用计数这一简单技术。也就是说 Python 内部记录着所有使用中的对象各有多少引用。 当一个对象的引用计数变为 0 时, 它被垃圾回收。 当对象被创建并(将其引用)赋值给变量时,该对象的引用计数就被设置为 1。

2.1. 引用计数的增加

在以下情况中,引用计数会增加: 1. 对象被创建 — x = 123 2. 另外的别名被创建 — y = x 3. 作为参数被传递给函数 — foobar(x) 4. 成为容器对象的元素 — myList = [1, x, 5]

2.2. 引用计数的减少

以下情况引用计数会减少: 1. 本地引用离开其作用范围 — 如函数调用结束 2. 对象别名显式销毁 — del y 3. 对象的一个别名被赋值为其他对象 — y = ’abc’ 4. 对象被从容器中移除 — myList.remove(x) 5. 容器本身销毁 — del myList

3. 垃圾收集

不再被使用的内存会被垃圾收集机制释放,而垃圾收集器就负责释放内存。 当对象引用计数为 0 就会立即出发内存回收动作。 我们都知道,java 是通过可达性判断对象是否需要回收的,他之所以不通过引用计数算法,是因为可能会有循环引用的存在。

下图展示了什么是循环引用:

这两个列表的引用计数永远不可能到0,如果仅仅依赖引用计数,那么他们将永远无法被收集。

在 python 中,list,set,dict,class,instance 等类型的对象可以持有其他对象的引用,他们被称为 container 对象,因此循环引用发生在 container 对象之间。 python 维护了三个可收集对象链表,用来收集和跟踪所有的 container 对象。 所有的 python 对象都由两个部分构成:PyObject_HEAD + 对象本身数据,而 container 对象则在其 PyObject_HEAD 前有一个 pyGC_Head,这个结构就是可收集对象链表节点结构。 在创建 container 对象时,解释器会调用 _PyObject_GC_TRACK 方法将对象加入到可收集对象链表中。 当对象销毁时,解释器会调用 _PyObject_GC_UNTRACK 方法将该 container 对象从可收集对象链表中移除。

4. 分代收集

分代收集是典型的为了提高垃圾收集的效率,所采用的“空间换时间的策略”。 python 也同样引入了分代收集的思想,所以前面提到 python 维护了三个可收集对象链表,所有属于同一”代”的内存块都链接在同一个链表中。 垃圾收集的频率随着“代”的存活时间的增大而减小,这是因为活得越长的对象,就越不可能是垃圾,就应该减少去收集的频率。 当一次垃圾收集过程中没有被回收的对象就会从当前的代自动移入到下一个代中。 每个代都有自己的容量阈值,当分代中的 container 对象超过了阈值时会触发垃圾回收。

5. 垃圾回收过程

python 采用标记-清除的方式来回收 container。 主要分以下六步: 1. 将所有比当前代年轻的分代中的对象都放到当前代链表中 2. 遍历对象链表,拷贝每个对象的引用计数到 PyGC_Head 中的 gc.gc_ref 作为引用计数副本 3. 判断对象是否符合循环引用,将循环引用的对象的 gc.gc_ref -1,从而获取有效引用计数 4. 将链表中引用计数为 0 与引用计数大于 0 的对象拆分成 reachable 和 unreachable 两个链表 5. reachable 中所有存活对象放入下一分代 6. 回收 unreachable 链表中的所有对象

6. python 中的 gc 模块

python 提供了 gc 模块,用来提供观察和手动使用gc的接口。

代码语言:javascript
复制
import gc

gc.set_debug(gc.DEBUG_STATS | gc.DEBUG_LEAK)
gc.collect()

7. 参考资料

http://python.jobbole.com/83548/?utm_source=blog.jobbole.com&utm_medium=relatedPosts。 http://python.jobbole.com/87843/ https://www.cnblogs.com/pinganzi/p/6646742.html#_label8。 https://www.jianshu.com/p/1e375fb40506。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-09-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 小脑斧科技博客 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 概述
  • 2. 引用计数
    • 2.1. 引用计数的增加
      • 2.2. 引用计数的减少
      • 3. 垃圾收集
      • 4. 分代收集
      • 5. 垃圾回收过程
      • 6. python 中的 gc 模块
      • 7. 参考资料
      相关产品与服务
      容器服务
      腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档