| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 数据结构与算法 -> python内存管理&垃圾回收原理 -> 正文阅读 |
|
[数据结构与算法]python内存管理&垃圾回收原理 |
“??引用计数器?为主,?标记清除?和?分代回收?为辅,+??缓存机制?。”?1.??引用计数器: ?1.1 环状的双向链表refchain:? 在python程序中,?创建?的任何一个?对象?都会?加入到?这个 refchain?双向链表?中。 例:?
操作系统会在内存中开辟一块空间存name这个对象,在内存中会为name这个对象创建一些数据 (即,一个结构体,包括?上一个对象位置、下一个对象位置,本数据的数据类型,本数据的引用个数(相同的)以及?具体数据(不同的)),new=name,操作系统不会为new开辟新空间,会在name开辟空间中的引用处标记2,即两个位置使用’wuhan‘这块空间。
C源码: ?1.2 类型封装的结构体: ?1.3 引用计数器: 当python程序运行时,会根据对象数据类型不同,找到对应的结构体,根据结构体中的字段来创建相关的数据,然后将对象添加到refchain这个双向链表中。 C源码中有两个关键的结构体:PyObject、PyVarObject。 创建对象的结构体中,都有ob_refcnt这个字段,这个就是引用计数器。创建对象的时候ob_refcnt的值默认是1,当有其他变量对这个对象进行引用时,引用计数器就会发生变化。 ~ 引用:?
~ 删除引用 :当对象的引用计数器为0时,意味着没有人再使用这个对象了,这个对象就是垃圾,对这个对象进行垃圾回收。回收:1.对象从refchain双向链表中移除;2.将对象进行销毁,把内存归还给操作系统。
1.4 引用计数器一个bug ,即循环引用问题 : 实际上del v1 和del v2 之后没有对两个列表进行引用的对象了,但是引用计数器不为0,不能被回收,形成垃圾,占用内存。 2.??标记清除: 标记清除?引入的目的:?为了解决引用计数器循环引用的不足。 标记清除?的实现:在python的底层中再维护一个链表?,链表中放可能存在循环引用的对象(如 list \ tuple \ dict \ set)。 某种情况下,在python内部会去扫描,可能存在循环引用的链表中的每个元素,检查是否有循环引用,如果有,则让双方的引用计数器-1,如果双方的引用计数器都为0,则是垃圾,该被回收;如果双方的引用计数器不为0,则不动该对象。每个元素的子元素都要被扫描一次。 标记清除 问题: a. 什么时候扫描? b.?每个元素的子元素都要被扫描一次,可能存在循环引用的这个链表?扫描的代价大!耗时久。 3.??分代回收: 分代回收?引入目的:为解决标记清除的问题; 分代回收?实现:将可能存在循环引用的对象?维护成?3个链表:0代、1代、2代?。每一代都是一个双向链表。 分代回收?扫描时间: 0代:0代对象个数达到700个,扫描一次; 1代:0代扫描10次,1代扫描一次; 2代:1代扫描10次,2代扫描一次; 分代回收?过程:创建对象,把有可能存在循环引用的对象加入到refchain和0代链表,0代扫描,ob_refcnt自减1,如果ob_refcnt值为0,进行垃圾回收;否则把数据从0代?升级?到1代,0代里扫描后,0代理就没有数据了,该回收的回收,该升级的升级。 4.小结 : 1)在python中维护了一个refchain的双向环状链表,这个链表存储程序创建的所有对象。 2)每种类型的对象中都包含一个ob_refcnt引用计数器的值,当有引用时ob_refcnt+1,删除引用时ob_refcnt-1;当引用计数器的值变为0时进行垃圾回收(对象销毁,从refchain中移除该对象)。 3)但是,在python中对于那些可以有多个元素组成的对象(list、tuple、set、dict),可能存在循环引用的问题,为了解决这个问题,python引入了标记清除和分代回收。也就是在python内部维护了四个链表:refchain(维护所有对象),2代(10次),1代(10次),0代(700个对象)。在源码内部当达到各自的阈值时,就会触发扫描链表进行标记清除,即有循环引用则各自-1。 4)python的源码内部在上述的流程中提出了优化机制 :缓存机制。 5.?缓存机制:? ?5.1 池:(int) 为避免重复创建和销毁一些常见的对象,维护池。 启动解释器时,python内部帮我们创建:-5,-4,......,257?,引用如上这期间的数据不会再创建新对象,直接引用小数据池中的数据对象,小数据池中的对象永远不会被回收。
?5.1 free_list:(float、list、tuple、dict)? 当引用计数器为0时,按理说应该回收该对象了?,但是python为了优化,不会直接回收,而是将这些数据添加到free_list列表中,以后再去创建对象,不重新开辟内存,而是直接使用free_list。free_list是有个数限制的,如80个。free_list满了,放不下的数据,才会被销毁。
由上,当引入计数器为0时,有时候直接销毁,有时候被缓存管理起来。? ? int、float、str对象只会放到refchain中,ob_refcnt=0,放到free_list中(未满),free_list满了销毁。 dict、list、set、tuple对像会放到refchain中,以及0代,ob_refcnt=0,放到free_list中(未满),free_list满了销毁。 ?整理 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/26 13:41:36- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |