Python全系列 教程
3567个小节阅读:5929.7k
目录
鸿蒙应用开发
C语言快速入门
JAVA全系列 教程
面向对象的程序设计语言
Python全系列 教程
Python3.x版本,未来主流的版本
人工智能 教程
顺势而为,AI创新未来
大厂算法 教程
算法,程序员自我提升必经之路
C++ 教程
一门通用计算机编程语言
微服务 教程
目前业界流行的框架组合
web前端全系列 教程
通向WEB技术世界的钥匙
大数据全系列 教程
站在云端操控万千数据
AIGC全能工具班
A A
White Night
Python 程序启动后,内部可能会创建大量对象。如果每次执行标记清除法时,都需要遍历所有对象,多半会影响程序性能。为此,Python 引入分代回收机制——将对象分为若干“代”( generation ),每次只处理某个代中的对象,因此 GC 卡顿时间更短。
考察对象的生命周期,可以发现一个显著特征:一个对象存活的时间越长,它下一刻被释放的概率就越低。我们应该也有这样的亲身体会:经常在程序中创建一些临时对象,用完即刻释放;而定义为全局变量的对象则极少释放。
因此,根据对象存活时间,对它们进行划分就是一个不错的选择。对象存活时间越长,它们被释放的概率越低,可以适当降低回收频率;相反,对象存活时间越短,它们被释放的概率越高,可以适当提高回收频率。
对象存活时间 | 释放概率 | 回收频率 |
---|---|---|
长 | 低 | 低 |
短 | 高 | 高 |
Python 内部根据对象存活时间,将对象分为 3 代(见 Include/internal/mem.h ):
xxxxxxxxxx
11#define NUM_GENERATIONS 3
随着时间的推进,程序冗余对象逐渐增多,达到一定阈值,系统进行回收。
这 3 个代分别称为:初生代、中生代 以及 老生代。当这 3 个代初始化完毕后,对应的 gc_generation 数组大概是这样的:
xxxxxxxxxx
41import gc
2#python 中内置模块gc触发
3print(gc.get_threshold()) #查看gc默认值
4#输出(700, 10, 10)
第一代链表:
当第一代达到700,就开始检测哪些对象引用计数变成0了,把不是0的放到第二代链表里,此时第一代链表就是空了,当再次达到700时,就再检测一遍。
第二代链表:
当第二代链表达到10,就检测一次。
第三代链表:
第三代链表检测10之后,第三代链表检测一次。
xxxxxxxxxx
121import gc
2#返回一个元组,分别获取这三代当前计数
3gc.get_count()
4
5#返回一个元组,分别获取这三代当前的收集阈值
6gc.get_threshold()
7
8#设置阈值
9gc.set_threshold()
10
11#关闭gc垃圾回收机制
12gc.disable()
实时效果反馈
1. Python 内部采用引用计数法,为每个对象维护引用次数,并据此回收不再需要的垃圾对象。由于引用计数法存在重大缺陷,循环引用时有内存泄露风险,因此 Python还采用 标记清除法来回收存在循环引用的垃圾对象。此外,为了提高垃圾回收( GC )效率,Python还引入了 ______ 。
A Python缓存机制
B 分代回收机制
C intern机制
D free_list机制
答案
1=>B
内存管理机制小结:
Python是由C语言开发的,底层操作都是基于C语言实现,Python中创建每个对象,内部都会与C语言结构体维护一些值。PyObject结构体(上一个对象、下一个对象、类型、引用个数)。PyVarObject结构体(PyObject,容量个数)。
在创建对象时,每个对象至少内部有4个值,双向链表指向上一个对象(ob_prev),下一个对象(ob_next)、类型(ob_type)、引用计数(ob_refcnt)。之后会对内存中的数据进行初始化,初始化本质:引用计数器赋值=1。然后将对象添加到双向链表refchain中。以后再有其他变量指向该对象,引用计数器+1,如果销毁某个变量,则引用计数器-1。当引用计数器等于0时,则进行垃圾回收。但是在内部可能存在缓存机制,例如:float、list、int,最开始不会真正销毁,而是放在free_list的链表中,以后再创建同类数据时,会先去free_list链表中取出对象,然后再对对象初始化。