Python 内存管理机制和垃圾回收机制

内存管理

Python中的内存管理机制的层次结构提供了4层,其中最底层则是C运行的mallocfree接口,往上的三层才是由Python实现并且维护的。

第一层则是在第0层的基础之上对其提供的接口进行了统一的封装,这是因为虽然不同的操作系统都提供标准定义的内存管理接口,但是对于某些特殊的情况不同的操作系统都不同的行为,比如说调用malloc(0),有的操作系统会返回NULL,表示内存申请失败;然而有的操作系统会返回一个貌似正常的指针,但是这个指针所指的内存并不是有效的。为了广泛的移植性,Python必须保证相同的语义一定代表相同的运行行为。

在第二层内存管理机制上,Python构建了更高抽象的内存管理策略,比如说一些常用对象,包括整数对象、字符串对象等等。

第三层主要是对象缓冲池机制,它基于在第二层的内存池。

内存池

Python为了避免频繁的申请和删除内存所造成系统切换于用户态和核心态的开销,从而引入了内存池机制,专门用来管理小内存的申请和释放。整个小块内存的内存池可以视为一个层次结构,其一共分为4层,从下之上分别是block、pool、arena和内存池。需要说明的是:block、pool和area都是代码中可以找到的实体,而最顶层的内存池只是一个概念上的东西,表示Python对于整个小块内存分配和释放行为的内存管理机制。

注意,内存大小以256字节为界限,大于则通过malloc进行分配,小于则通过内存池分配。

如下图:

  1. block:最小的内存单元,大小为8的整数倍。有很多种类的block,不同种类的block都有不同的内存大小,申请内存的时候只需要找到适合自身大小的block即可,当然申请的内存也是存在一个上限,如果超过这个上限,则退化到使用最底层的malloc进行申请。

  2. pool:一个pool管理着一堆有固定大小的内存块,其大小通常为一个系统内存页的大小。

  3. arena:多个pool组合成一个arena。

  4. 内存池:一个整体的概念。

参考文章:

Python内存池管理与缓冲池设计

垃圾回收

Python的GC模块主要运用了引用计数来跟踪和回收垃圾。在引用计数的基础上,还可以通过“标记-清除”解决容器对象可能产生的循环引用的问题。通过分代回收以空间换取时间进一步提高垃圾回收的效率。

引用计数

原理:当一个对象的引用被创建或者复制时,对象的引用计数加1;当一个对象的引用被销毁时,对象的引用计数减1,当对象的引用计数减少为0时,就意味着对象已经再没有被使用了,可以将其内存释放掉。

优点:引用计数有一个很大的优点,即实时性,任何内存,一旦没有指向它的引用,就会被立即回收,而其他的垃圾收集技术必须在某种特殊条件下才能进行无效内存的回收。

缺点:但是它也有弱点,引用计数机制所带来的维护引用计数的额外操作与Python运行中所进行的内存分配和释放,引用赋值的次数是成正比的,这显然比其它那些垃圾收集技术所带来的额外操作只是与待回收的内存数量有关的效率要低。同时,引用技术还存在另外一个很大的问题-循环引用,因为对象之间相互引用,每个对象的引用都不会为0,所以这些对象所占用的内存始终都不会被释放掉。如下:

a = []
b = []
a.append(b)
b.append(a)
print a
[[[…]]]
print b
[[[…]]]

标记-清除

标记-清除只关注那些可能会产生循环引用的对象,显然,像是PyIntObject、PyStringObject这些不可变对象是不可能产生循环引用的,因为它们内部不可能持有其它对象的引用。Python中的循环引用总是发生在container对象之间,也就是能够在内部持有其它对象的对象,比如list、dict、class等等。这也使得该方法带来的开销只依赖于container对象的的数量???

原理:1. 寻找跟对象(root object)的集合作为垃圾检测动作的起点,跟对象也就是一些全局引用和函数栈中的引用,这些引用所指向的对象是不可被删除的;2. 从root object集合出发,沿着root object集合中的每一个引用,如果能够到达某个对象,则说明这个对象是可达的,那么就不会被删除,这个过程就是垃圾检测阶段;3. 当检测阶段结束以后,所有的对象就分成可达和不可达两部分,所有的可达对象都进行保留,其它的不可达对象所占用的内存将会被回收,这就是垃圾回收阶段。(底层采用的是链表将这些集合的对象连接在一起)

缺点:标记和清除的过程效率不高。

分代回收

原理:将系统中的所有内存块根据其存活时间划分为不同的集合,每一个集合就成为一个“代”,Python默认定义了三代对象集合,垃圾收集的频率随着“代”的存活时间的增大而减小。也就是说,活得越长的对象,就越不可能是垃圾,就应该减少对它的垃圾收集频率。那么如何来衡量这个存活时间:通常是利用几次垃圾收集动作来衡量,如果一个对象经过的垃圾收集次数越多,可以得出:该对象存活时间就越长。

参考文章

深入分析 Python 的垃圾回收机制

Python垃圾回收机制 总结的更多相关文章

  1. python垃圾回收机制与小整数池

    python垃圾回收机制 当引用计数为0时,python会删除这个值. 引用计数 x = 10 y = x del x print(y) 10 引用计数+1,引用计数+1,引用计数-1,此时引用计数为 ...

  2. python垃圾回收机制:引用计数 VS js垃圾回收机制:标记清除

    js垃圾回收机制:标记清除 Js具有自动垃圾回收机制.垃圾收集器会按照固定的时间间隔周期性的执行. JS中最常见的垃圾回收方式是标记清除. 工作原理 当变量进入环境时,将这个变量标记为"进入 ...

  3. 浅析Python垃圾回收机制!

    Python垃圾回收机制 目录 Python垃圾回收机制 1. 内存泄露 2. Python什么时候启动垃圾回收机制? 2.1 计数引用 2.2 循环引用 问题:引用计数是0是启动垃圾回收的充要条件吗 ...

  4. 简述Python垃圾回收机制和常量池的验证

    目录 通过代码验证python解释器内部使用了常量池 Python的引入 变量的引入 为什么要有变量 定义变量 常量引入 常量池引入 Python解释器 Python变量存储机制 Python垃圾回收 ...

  5. 从 CPython 源码角度看 Python 垃圾回收机制

    环状双向链表 refchain 在 Python 程序中创建的任何对象都会被放到 refchain 链表中,当创建一个 Python 对象时,内部实际上创建了一些基本的数据: 上一个对象 下一个对象 ...

  6. python垃圾回收机制的一些理解

    概览:       主要通过 引用计数来进行垃圾收集, 就是说,当一个对象没有被其他对象引用的时候,会释放掉内存.     但是会有一些循环引用的对象,通过上面的方法,是没有办法清除掉的.所以,pyt ...

  7. Python垃圾回收机制详解

    一.垃圾回收机制 Python中的垃圾回收是以引用计数为主,分代收集为辅.引用计数的缺陷是循环引用的问题. 在Python中,如果一个对象的引用数为0,Python虚拟机就会回收这个对象的内存. #e ...

  8. python 垃圾回收机制的思考

    一.前言 Python 是一门高级语言,使用起来类似于自然语言,开发的时候自然十分方便快捷,原因是Python在背后为我们默默做了很多事情,其中一件就是垃圾回收,来解决内存管理,内存泄漏的问题. 内存 ...

  9. Python垃圾回收机制--完美讲解!

    转自: http://www.jianshu.com/p/1e375fb40506 先来个概述,第二部分的画述才是厉害的. Garbage collection(GC) 现在的高级语言如java,c# ...

随机推荐

  1. Java注解--实现动态数据源切换

    当一个项目中有多个数据源(也可以是主从库)的时候,我们可以利用注解在mapper接口上标注数据源,从而来实现多个数据源在运行时的动态切换. 实现原理 在Spring 2.0.1中引入了Abstract ...

  2. mysql 查询缓存配置和查看

    Mysql 查询缓存 查询缓存的作用就是当查询接收到一个和之前同样的查询,服务器将会从查询缓存种检索结果,而不是再次分析和执行上次的查询.这样就大大提高了性能,节省时间. 1.配置查询缓存 修改配置文 ...

  3. MySQL(二)--事务与视图

    一.事务 1.提交 2.回滚 3.ACID特性 二.视图 1.创建视图 2.删除视图 3.更新视图 4.使用视图 三.子查询 1. 使用子查询 2. 标量子查询 3. 关联子查询 一.事务 在 RDB ...

  4. 几个SQL语句(备忘)

    1.三涨停 select biao1.代码,biao1.名称 from biao1,biao2,biao3 where (biao1.涨幅+ biao2.涨幅+biao3.涨幅)>0.27 an ...

  5. 设备常用框架framework

    framework名称 framework说明 framework文档 Accelerate.framework 包含加速数学和DSP函数 http://developer.apple.com/iph ...

  6. Bash : 索引数组

    Bash 提供了两种类型的数组,分别是索引数组(indexed array)和关联数组(associative array).本文主要介绍索引数组的基本用法. 索引数组的基本特点 Bash 提供的数组 ...

  7. C#面试题记录

    最怕的就是面试,每每到找工作的时候感觉压力山大,每次都要提前刷点题目去面对.所以这里自己对以后需要了解的知识做一个记录,方便自己随时的补充和深入了解,也给现在的自己留下一点点的印记,给未来留下一点回忆 ...

  8. POJ 2195 Going Home (带权二分图匹配)

    POJ 2195 Going Home (带权二分图匹配) Description On a grid map there are n little men and n houses. In each ...

  9. blob 和 sas

    Blob是什么? 请看上篇文章简单总结下关于blob的图片上传 在使用Blob图片上传的时候碰到许多问题,比如如何使用用户名密码下载文件啊什么的 今天就记录一下我碰到的最大的问题 如何匿名去访问你上传 ...

  10. app耗电优化之二 使用电源管理来安排任务

    PowerManager 电源管理(电源使用管理).主要管理设备启动,保持活动,休眠,唤醒.其中为了保持任务,提供了PowerManager.WakeLock(唤醒锁).执行任务时持有这个唤醒锁,就可 ...