zoukankan      html  css  js  c++  java
  • 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虚拟机退出的时候

     
     




  • 相关阅读:
    WPF入门(一):简单的演示
    代码的演化DI(理解依赖注入di,控制反转ioc)
    WPF入门(三):简单绑定 绑定到页面元素
    WPF入门(四):简单绑定 静态资源绑定
    WPF入门(六)样式Style
    WPF入门(八)布局(layout) port 2
    js select onchange
    js this指向
    js 两个日期之间有多少个星期几
    js table的所有td 按行合并
  • 原文地址:https://www.cnblogs.com/1314520xh/p/12879073.html
Copyright © 2011-2022 走看看