zoukankan      html  css  js  c++  java
  • Python垃圾回收机制

    垃圾回收机制

    垃圾回收机制(Garbage Collection),简称GC,是Python解释器自带的机制,专门用来进行垃圾回收。

    在定义一个变量时,会申请内存空间,当该变量使用完毕,也应该释放掉该变量所占用的内存空间,在C中需要程序员手动释放掉内存,而Python则由GC机制进行回收。

    无论何种垃圾回收机制,一般都分为两个阶段:垃圾检测和垃圾回收。垃圾检测就是区分已分配内存中的“可回收”和“不可回收”内存。垃圾回收则是使操作系统重新掌握垃圾检测阶段所标识出来的“可回收”内存块。

    所谓垃圾回收,并不是直接把这块内存的数据直接清空了,而是将使用权重新交给了操作系统,不会应用程序霸占了。

    什么是垃圾

    1. 当一个变量调用完毕,且后续不再需要时,便是垃圾。
    2. 当指向该变量地址的变量名指向另一个地址时,原变量内存地址无法被访问,此时该变量也是垃圾。

    Python定义变量原理

    在Python中一切皆对象,内存空间分为栈区和堆区,其中:

    栈区:

    • 保存变量名与变量值的内存地址的关联关系

    堆区:

    • 保存实际的变量值,也是内存管理回收的地方

    GC机制原理

    1. 引用计数
    2. 分代回收
    3. 标记清除

    引用计数

    引用计数原理是每个对象维护一个ob_refcnt,用来记录当前对象被引用的次数。该方式的优点是:一旦引用计数为0,则会直接被回收。

    引用计数加1的情况:

    • 对象被创建:x=10
    • 对象被引用:y=x
    • 对象被当做参数传入:func(x)
    • 对象作为容器类型的元素

    引用计数减1的情况:

    • 显示销毁对象的引用:del x
    • 对象的引用指向其他对象:x = 20
    • 对象的引用离开了它的作用域,比如函数的局部变量,在函数执行完毕时,也会被销毁(除非取栈帧)
    • 对象的引用所在的容器被销毁,或者从容器中删除等

    查看引用计数:

    使用sys.getrefcount(obj),但是由于对象会作为参数传进去,所以引用计数会+1。

    直接引与间接引用:

    直接引用:从栈区直接指向到实际值的引用。

    间接引用:从栈区指向堆区后,再次引用才能到达实际存放值的内存,容器类型。

    引用计数的缺陷:

    循环引用:当两个容器类型对象,内部分别将对方添加为元素,此时即便删除了变量名,这两个对象的引用计数容不能为0。

    l1 = []
    l2 = []
    l1.append(l2)
    l2.append(l1)
    del l1,l2
    

    此时虽然没有通过栈区指向堆区,但它们彼此指向,导致引用计数不为0,如果程序一直运行的话,是有可能发生内存泄露的。

    标记清除

    标记清除就是为了解决“循环引用”的问题。其过程为

    1. 寻找根对象(root object)的集合,root object就是一些全局引用和函数栈的引用。
    2. 遍历root object集合,对每一个引用可以直接或间接访问到的对象标记为存活的对象,其余均为非存活对象,应该被清除。
    3. 遍历堆中的所有对象,对未被标记的对象全部清除掉。

    分代回收

    基于引用计数的回收机制,每次进行内存回收,都需要把对象的引用计数遍历一遍,这是非常耗时的,于是就引入了分代回收来提升效率,分代回收采用的是“空间换时间”策略。

    分代

    在经历多次扫描的情况下,都没有被回收的对象,那么就认为,该变量是常用变量,对其的扫描频率会降低。具体的原理为:

    分代指的是根据存活时间来为变量划分不同等级,也就是不同的代,垃圾回收的扫描频率会随着“代”的存活时间增大而减小。

    “代”可以想象成链表,属于同一个代的对象都被连接在同一个链表中。在Python中总共存在三条链表,说明所有的对象可以分为三代:零代、一代、二代。一个“代”就是一条可收集对象链表。

    第0代链表最多可容纳700个对象,一旦超过700这个阈值,那么会立即出发垃圾回收机制。

    1代链表和2代链表触发垃圾回收的条件又是什么呢?当0代链表触发了10次垃圾回收的时候,会触发一次1代链表的垃圾回收。当1代链表触发了10次垃圾回收的时候,会触发一次2代链表的垃圾回收。

    • 在清理1代链表的时候,会顺带清理0代链表
    • 在清理2代链表的时候,会顺带清理0代链表和1代链表

    gc模块

    gc模块底层就是gcmodule,该模块是用C写的,当python编译好时,就内嵌在解释器里面了。我们可以导入它,但是在Python安装目录上看不到。

    gc.enable:开启垃圾回收

    这个函数表示开启垃圾回收机制,默认是自动开启的。

    gc.disable:关闭垃圾回收

    import gc
    	
    # 关掉gc
    gc.disable()
    
    # 开启
    gc.enable()
    
  • 相关阅读:
    html_Dom
    html_javascript
    html_之css
    协程
    进程和线程的总结
    html_基础标签
    html_头部<meta>设置
    Python_queue单项队列
    Python_paramiko模块
    Python_多进程multiprocessing
  • 原文地址:https://www.cnblogs.com/ChiRou/p/14905067.html
Copyright © 2011-2022 走看看