python里面的垃圾回收机制
Posted 行走在云端
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python里面的垃圾回收机制相关的知识,希望对你有一定的参考价值。
文章链接:https://www.jianshu.com/p/1e375fb40506
Garbage collection(GC)
现在的高级语言如java,c#等,都采用了垃圾收集机制,而不再是c,c++里用户自己管理维护内存的方式。自己管理内存极其自由,可以任意申请内存,但如同一把双刃剑,为大量内存泄露,悬空指针等bug埋下隐患。
对于一个字符串、列表、类甚至数值都是对象,且定位简单易用的语言,自然不会让用户去处理如何分配回收内存的问题。
python里也同java一样采用了垃圾收集机制,不过不一样的是:
python采用的是引用计数
机制为主,标记-清除
和分代收集
两种机制为辅的策略
GC系统所承担的工作远比“垃圾回收”多得多。它们负责三个重要任务:
- 为新生成的对象分配内存
- 识别那些垃圾对象
- 从垃圾对象回收内存
如果将应用程序比作人的身体:所有你所写的那些优雅的代码,业务逻辑,算法,应该就是大脑。垃圾回收就是应用程序那颗跃动的心。像心脏为身体其他器官提供血液和营养物那样,垃圾回收器为你的应该程序提供内存和对象。如果垃圾回收器停止工作或运行迟缓,像动脉阻塞,你的应用程序效率也会下降,直至最终死掉。
gc模块的自动垃圾回收机制
必须要import gc模块,并且is_enable()=True才会启动自动垃圾回收。
这个机制的主要作用就是发现并处理不可达的垃圾对象。
垃圾回收=垃圾检查+垃圾回收
1、引用计数机制:
python里每一个东西都是对象,它们的核心就是一个结构体:PyObject
typedef struct_object {
int ob_refcnt; #引用计数
struct_typeobject *ob_type;
} PyObject;
PyObject是每个对象必有的内容,其中ob_refcnt
就是做为引用计数。当一个对象有新的引用时,它的ob_refcnt
就会增加,当引用它的对象被删除,它的ob_refcnt
就会减少
#define Py_INCREF(op) ((op)->ob_refcnt++) //增加计数 #define Py_DECREF(op) \\ //减少计数 if (--(op)->ob_refcnt != 0) \\ ; \\ else \\ __Py_Dealloc((PyObject *)(op))
import sys class A(object): def __init__(self): """初始化对象""" print (\'object born id:%s\'%str(hex(id(self)))) def f1(): """循环引用变量与删除变量""" while True: c1=A() del c1 def func(c): """getrefcount() 返回对象的引用计数""" print (\'object refcount is:\',sys.getrefcount(c)) if __name__==\'__main__\': # 生成对象 a=A() func(a) # 增强引用 b=a func(a) # 销毁引用 del b func(a) 结果: object born id:0x1043059b0 object refcount is: 4 object refcount is: 5 object refcount is: 4
gc方式1:引用计数
若此对象无其他对象引用,则立马回收掉
优点:简单、实时(将处理垃圾时间分摊到运行代码时,而不是等到一次回收)
缺点:
1.保存对象引用数会占用一点点内存空间
2.每次执行语句都可能更新引用数,不再使用大的数据结构时,会引起大量对象被回收
3.不能处理循环引用的情况
gc方式2:标记-清除(Mark—Sweep)
此方式主要用来处理循环引用的情况,只有容器对象(list、dict、tuple,instance)才会出现循环引用的情况
处理过程 1.将所有容器对象放到一个双向链表中(链表为了方便插入删除),这些对象为0代 2.循环遍历链表,如果被本链表内的对象引入,自身的被引用数-1,如果被引用数为0,则触发引用计数回收条件,被回收掉 3.未被回收的对象,升级为1代
『标记清除(Mark—Sweep)』算法是一种基于追踪回收(tracing GC)技术实现的垃圾回收算法。它分为两个阶段:第一阶段是标记阶段,GC会把所有的『活动对象』打上标记,第二阶段是把那些没有标记的对象『非活动对象』进行回收。那么GC又是如何判断哪些是活动对象哪些是非活动对象的呢?
对象之间通过引用(指针)连在一起,构成一个有向图,对象构成这个有向图的节点,而引用关系构成这个有向图的边。从根对象(root object)出发,沿着有向边遍历对象,可达的(reachable)对象标记为活动对象,不可达的对象就是要被清除的非活动对象。根对象就是全局变量、调用栈、寄存器。
何时触发
1.被引用为0时,立即回收当前对象
2.达到了垃圾回收的阈值,触发标记-清除
3.手动调用gc.collect()
4.Python虚拟机退出的时候
以上是关于python里面的垃圾回收机制的主要内容,如果未能解决你的问题,请参考以下文章