python垃圾回收算法
标准python垃圾回收器由两部分组成,即引用计数回收器和分代垃圾回收器(即python包中的gc module
)。其中,引用计数模块不能被禁用,而GC模块可以被禁用。
引用计数算法
python中每个变量都是对象,每个对象核心都包含一个结构体PyObject:
typedef struct_object {
int ob_refcnt;
struct_typeobject *ob_type;
} PyObject;
其中ob_refcnt
变量记录了这个对象被引用的数量,当这个对象的引用被赋值给另一个变量或者这个引用被删除(如del a
)。那么ob_refcnt
就会随之加1或者减1。引用计数增加的场景有:
- 赋值操作
- 参数传递
- 添加object到list末尾
如果某个对象的引用计数为0,那么python会立马调用函数释放内存空间,此时可能导致这个对象引用的其他对象引用计数也为0,因此一个对象消亡可能引起一连串对象内存空间被释放。
一般说来,全局变量(定义在函数,类和代码块之外的变量)随python进程退出而释放,因此引用计数永远不会减为0。局部变量(定义在函数,类和代码块之内的变量)反之。
引用计数算法原理简单明了,但是存在循环引用,线程锁和内存性能开销等问题。
分代垃圾回收算法
引用计数算法最大问题就是循环引用,这种情况下循环引用的每个对象的引用计数最终都不会归零,如下图所示:

因此,python在gc module
实现了循环检测算法来解决这个问题。循环引用只可能发生在容器对象之间,因此,GC循环检测也只对容器对象使用。对于只包含常量的容器(如包含常量的tuple),GC也会把这部分排除掉。
GC将容器对象分为3代,定期清理每代的垃圾对象。新分配的对象总是在第0代,如果经历过一次垃圾回收依然存活则移入下一代。新生代的回收频率比老年代高,大部分新对象很快就会释放,因此生命周期都只是停留在第0代。这种分代回收方式可以提高GC性能,减少停顿时间。
GC进行时需要停止程序的执行以免引用关系改变。
为了确定何时可以执行垃圾回收,GC每一代维护都会count和threshold两个变量,其中count=上一次垃圾回收后分配的新对象-上一次垃圾回收后已经消亡对象(因为引用计数为0而被释放)
,每次对象创建时候都会比较count和threshold大小,如果count>threshold
,python就会启动垃圾回收进程。
以下详细说明CPython循环检测的原理,CPython维护两个双向链表:一个是需要检测的对象关系链表(objects list),一个是存放无法访达的对象链表(Unreachable list)。
- 如下图所示,假设现在清理的是第0代的垃圾对象。左边的需要扫描的对象列表中link4是一个循环引用。varA是link1的外部引用,可能是其他代的对象。每个对象除了有一个引用计数变量ref count外,还维护一个gc_ref变量,初始时ref count=gc_ref.

- GC遍历objects list每个对象,将这个对象所引用的其他对象的gc_ref减1。

- GC将步骤2中gc_ref=0的对象挪到Unreachable list中,下图表示将已经处理的link3和link4移到Unreachable list,但是还没有处理link1和link2.

- 当GC扫描link1时候,发现gc_ref=1,是可以访达的,那么GC就会循环遍历link1引用的对象,将其标记为可以访达。因为link3经过此轮后标记为可以访达,那么就会将其从Unreachable list移到之前的list中。

- GC扫描完所有的对象后,就会启动垃圾回收进程,将Unreachable list中的对象清理掉。
为了性能考虑,我们应该尽量避免循环引用,可以使用weakref
module,weakref.ref
不会增加对象的引用计数并且对象被回收后返回None
。此外,可以使用gc.disable()
手动关闭GC垃圾回收,这在某些特殊情况下有帮助。
参考资料
[1] Garbage collection in Python: things you need to know
[2] Python垃圾回收机制
[3] The Garbage Collector
[4] Python垃圾回收(GC)三层心法,你了解到第几层
python垃圾回收算法的更多相关文章
- 《垃圾回收的算法与实现》——Python垃圾回收
Python垃圾回收 python采用引用计数法进行垃圾回收 Python内存分配 python在分配内存空间时,在malloc之上堆放了3个独立的分层. python内存分配时主要由arena.po ...
- Python垃圾回收机制
引用计数Python默认的垃圾收集机制是“引用计数”,每个对象维护了一个ob_ref字段.它的优点是机制简单,当新的引用指向该对象时,引用计数 引用计数 Python默认的垃圾收集机制是“引用计数”, ...
- 深入理解java虚拟机【垃圾回收算法】
Java虚拟机的内存区域中,程序计数器.虚拟机栈和本地方法栈三个区域是线程私有的,随线程生而生,随线程灭而灭:栈中的栈帧随着方法的进入和退出而进行入栈和出栈操作,每个栈帧中分配多少内存基本上是在类结构 ...
- (转)《深入理解java虚拟机》学习笔记3——垃圾回收算法
Java虚拟机的内存区域中,程序计数器.虚拟机栈和本地方法栈三个区域是线程私有的,随线程生而生,随线程灭而灭:栈中的栈帧随着方法的进入和退出而进行入栈和出栈操作,每个栈帧中分配多少内存基本上是在类结构 ...
- C/C++中几种经典的垃圾回收算法
1.引用计数算法 引用计数(Reference Counting)算法是每个对象计算指向它的指针的数量,当有一个指针指向自己时计数值加1:当删除一个指向自己的指针时,计数值减1,如果计数值减为0,说明 ...
- 深入理解java垃圾回收算法
Java虚拟机的内存区域中,程序计数器.虚拟机栈和本地方法栈三个区域是线程私有的,随线程生而生,随线程灭而灭:栈中的栈帧随着方法的进入和退出而进行入栈和出栈操作,每个栈帧中分配多少内存基本上是在类结构 ...
- Python垃圾回收机制--完美讲解!
转自: http://www.jianshu.com/p/1e375fb40506 先来个概述,第二部分的画述才是厉害的. Garbage collection(GC) 现在的高级语言如java,c# ...
- C++ 几种经典的垃圾回收算法
之前遇到了一篇好文(https://blog.csdn.net/wallwind/article/details/6889917)准备学习一下的,课程繁忙就忘记了,今日得闲,特来补一下. 自己写一遍加 ...
- JVM垃圾回收算法及回收器详解
引言 本文主要讲述JVM中几种常见的垃圾回收算法和相关的垃圾回收器,以及常见的和GC相关的性能调优参数. GC Roots 我们先来了解一下在Java中是如何判断一个对象的生死的,有些语言比如Pyth ...
随机推荐
- 设计模式之Mediator模式(笔记)
中介者模式:用一个中介对象来封装一系列的对象交互. 中介者使各对象不须要显式的相互引用,从而使其耦合松散.并且能够独立的改变它们之间的交互. 使用场合:中介者模式一般应用于一组对象以定义良好可是复杂的 ...
- js模拟支付宝提交表单
弄过支付宝的程序猿可能都知道,里面有非常多地方都用到了自提交表单的方式,支付宝的接口通过请求API的形式取得server返回的表单字符串,使用out.print("表单字符串")在 ...
- JavaScript中的Array对象方法调用
方法concat for 循环与for in 循环 <html> <head> <script type="text/javascript"> ...
- pig 调试(explain&illerstrate)
grunt> cat t.txt kw1 2 kw3 1 kw2 4 kw1 5 kw2 2 cat test.pig A = LOAD '/user/input/t.txt' as (k:ch ...
- 最简单的TCP程序
网络编程里面最简单的一个tcp程序,把一个文件从客户端上传到服务器端,上传成功后服务器端提示上传完成.代码不多,一个服务端和一个客户端. 服务端代码: import java.io.FileOutpu ...
- 《剑指offer》二维数组中的查找
一.题目描述 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. 二.输入描述 ar ...
- 如何用Java实现反转排序
摘要:反转排序是将原先已经排序好了的重新排序,是原来的数组元素的顺序反转过来.假设原来的数组顺序是{6,5,4,3,2,1},反转之后的顺序就是{1,2,3,4,5,6}.这个排序的算法不是很难,代码 ...
- ASCII码对应表chr(9)、chr(10)、chr(13)、chr(32)、chr(34)、chr(39)、chr(..
chr(9) tab空格 chr(10) 换行 chr(13) 回车 Chr(13)&chr(10) 回车换行 chr(32) 空格符 ...
- [笔记-图论]Dijkstra
用于求正权有向图 上的 单源最短路 优化后时间复杂度O(mlogn) 模板 // Dijkstra // to get the minumum distance with no negtive way ...
- 关于FAT32分区的U盘4GB文件的测试
关于FAT32分区的U盘4GB文件的测试 很多人都知道FAT32的分区,单文件大小不能超过4GB,关于这个问题就来测测看. FAT32最大文件大小为2的32次方,也就是4294967296 Byte, ...