python开发之内存分配与垃圾回收
一、内存分配
1. C语言源码
Python解释器由c语言开发完成,py中所有的操作最终都由底层的c语言来实现并完成,所以想要了解底层内存管理需要结合python源码来进行解释。Python的源码可以去官网下载source code,不要下载安装包,下载 Gzipped source tarball,解压完成后主要关注Include和Objects这两个文件。
#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内存管理中的基石,其中包含了:
-
2个结构体:
– PyObject,此结构体中包含3个元素。_PyObject_HEAD_EXTRA,用于构造双向链表。 ob_refcnt,引用计数器。 *ob_type,数据类型。
– PyVarObject,次结构体中包含4个元素(ob_base中包含3个元素)
ob_base,PyObject结构体对象,即:包含PyObject结构体中的三个元素。 ob_size,内部元素个数。
-
3个宏定义:
PyObject_HEAD,代指PyObject结构体。 PyVarObject_HEAD,代指PyVarObject对象。 _PyObject_HEAD_EXTRA,代指前后指针,用于构造双向队列。
Python中所有类型创建对象时,底层都是与PyObject和PyVarObject结构体实现,一般情况下由单个元素组成对象内部会使用PyObject结构体(float)、由多个元素组成的对象内部会使用PyVarObject结构体(str/int/list/dict/tuple/set/自定义类),因为由多个元素组成的话是需要为其维护一个 ob_size(内部元素个数)。
例如:当创建一个float对象时:
val = 3.14
当按照上述方式创建一个Float类型对象时,源码内部会先后执行如下代码:
/* Special free list
free_list is a singly-linked list of available PyFloatObjects, linked
via abuse of their ob_type members.
*/