首页 > 编程语言 > 详细

Python的内存管理和垃圾回收

时间:2020-05-03 22:44:29      阅读:48      评论:0      收藏:0      [点我收藏+]

内存管理

与Python对象创建相关的结构体

#define _PyObject_HEAD_EXTRA            \
    struct _object *_ob_next;               struct _object *_ob_prev;
     
#define PyObject_HEAD       PyObject ob_base;
 
#define PyObject_VAR_HEAD      PyVarObject ob_base;
 
 
typedef struct _object {
    _PyObject_HEAD_EXTRA // 用于构造双向链表
    Py_ssize_t ob_refcnt;  // 引用计数器
    struct _typeobject *ob_type;    // 数据类型
} PyObject;
 
 
typedef struct {
    PyObject ob_base;   // PyObject对象
    Py_ssize_t ob_size; /* Number of items in variable part,即:元素个数 */
} PyVarObject;

对Python内存管理理解

Python是由C语言开发。
Python中所有对象的创建均与C语言中的两个结构体有关,分别是Pyobject和PyVarobject。
在Python中创建由单个元素组成的对象时(比如float类型),会使用Pyproject结构体,在创建由多个元素组成的对象时,使用PyVarproject创建。
Pyobject内部维护了数据类型,引用计数器,和双向链表,PyVarproject内部比Pyobject多了一个元素个数。
在Python中,每创建一个对象,首先会开辟内存并对其进行初始化(引用计数器设为1),再将其对象添加到双向链表中(ref_chain)。
再对对象进行重复引用时,该对象的引用计数器(ob_refcnt)会增加1,删除变量时(del 变量)会找到该变量对应的对象的引用计数器进行减1操作,
如果计数器变为0,系统将会把该对象对应的内存作为垃圾(实际上会放到缓存链表free_list中,如果再次创建同类型(float和列表类型)数据时,不会重新开辟内存,就会把free_list中同类型的内存数据改变后,重新引用,减少了重新开辟内存的开销)。

验证回收后的内存会先放在free_list中:

技术分享图片

 

 会发现,删除float类型后,在创建float类型,不会重新开辟新内存。

垃圾回收

引用计数器为主,标记清除和分代回收为辅。

1:引用计数器:为零时作为垃圾回收。
2:标记清除:由于引用计数器无法解决循环引用的问题,多个元素组成的对象才可能造成循环引用。
   Python底层会将Python中所有对象分类成为两个链表,分别是由单个元素和多个元素组成的对象,Python内部会定期扫描由多个元素组成对象的链表,如果遇到循环引用,则让各自的计数器减1,如果此时计数器变为零则变成垃圾。
    
3:分代回收:由于在标记清除扫描链表时,链表对象比较多,并且为了设置对象扫描的优先级,设置了分代回收,分别是0代,1代,2代。0代扫描十次,才会扫描1代一次,如果发现对象仍被引用,则进行升级,级别越高,成为垃圾的几率越小,扫描次数也越小,减少了系统扫描造成的资源消耗。
  注:对象链表长度为700,扫描一次。

循环引用

a=[1,2]
b=[3,4]

a.append(b) #a=[1,2,b]
b.append(a) #b=[3,4,a]

del a
del b

#del a b后,原a,b对应的引用计数器仍为1,因此会在内存中一直存在。

 

Python的内存管理和垃圾回收

原文:https://www.cnblogs.com/sun-10387834/p/12824027.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!