大师兄的Python源码学习笔记(四十五): Python的多线程机制(七)
- Python所有的内存管理机制都有两套实现,由编译符号PYMALLOC_DEBUG控制:
- 当该符号被定义时,使用的是debug模式下的内存管理机制,这套机制在正常的内存管理动作之外,还会记录许多关于内存的信息,以方便Python在开发时进行调试。
- 当该符号未被定义时,进行正常的内存管理动作。
- 我们的焦点放在非debug模式下的内存管理机制上。
一、内存管理架构
-
Python中的内存管理机制被抽象成一种层次似的结果:
1. 第0层
- 第0层是操作系统提供的内存管理接口,比如C提供的malloc和free接口。
- 这一层由操作系统提供,Python不干涉这一层的行为。
- 从这一层往上全部由Python实现并维护。
2. 第1层
- 第1层基于第0层操作系统的管理接口包装而成。
- 为了最广泛的可移植性,这一层为Python提供一层统一的raw memory的管理接口。
Include\pymem.h
PyAPI_FUNC(void *) PyMem_RawMalloc(size_t size);
PyAPI_FUNC(void *) PyMem_RawCalloc(size_t nelem, size_t elsize);
PyAPI_FUNC(void *) PyMem_RawRealloc(void *ptr, size_t new_size);
PyAPI_FUNC(void) PyMem_RawFree(void *ptr);
Objects\obmalloc.c
void *
PyMem_RawMalloc(size_t size)
{
/*
* Limit ourselves to PY_SSIZE_T_MAX bytes to prevent security holes.
* Most python internals blindly use a signed Py_ssize_t to track
* things without checking for overflows or negatives.
* As size_t is unsigned, checking for size < 0 is not required.
*/
if (size > (size_t)PY_SSIZE_T_MAX)
return NULL;
return _PyMem_Raw.malloc(_PyMem_Raw.ctx, size);
}
void *
PyMem_RawCalloc(size_t nelem, size_t elsize)
{
/* see PyMem_RawMalloc() */
if (elsize != 0 && nelem > (size_t)PY_SSIZE_T_MAX / elsize)
return NULL;
return _PyMem_Raw.calloc(_PyMem_Raw.ctx, nelem, elsize);
}
void*
PyMem_RawRealloc(void *ptr, size_t new_size)
{
/* see PyMem_RawMalloc() */
if (new_size > (size_t)PY_SSIZE_T_MAX)
return NULL;
return _PyMem_Raw.realloc(_PyMem_Raw.ctx, ptr, new_size);
}
void PyMem_RawFree(void *ptr)
{
_PyMem_Raw.free(_PyMem_Raw.ctx, ptr);
}
- 可以看到,在第1层提供了类似C中malloc,calloc,realloc,free的语义。
- 此外,在第1层中,还提供了面向Python中类型的内存分配器:
Include\pymem.h
/*
* Type-oriented memory interface
* ==============================
*
* Allocate memory for n objects of the given type. Returns a new pointer
* or NULL if the request was too large or memory allocation failed. Use
* these macros rather than doing the multiplication yourself so that proper
* overflow checking is always done.
*/
#define PyMem_New(type, n) \
( ((size_t)(n) > PY_SSIZE_T_MAX / sizeof(type)) ? NULL : \
( (type *) PyMem_Malloc((n) * sizeof(type)) ) )
#define PyMem_NEW(type, n) \
( ((size_t)(n) > PY_SSIZE_T_MAX / sizeof(type)) ? NULL : \
( (type *) PyMem_MALLOC((n) * sizeof(type)) ) )
/*
* The value of (p) is always clobbered by this macro regardless of success.
* The caller MUST check if (p) is NULL afterwards and deal with the memory
* error if so. This means the original value of (p) MUST be saved for the
* caller's memory error handler to not lose track of it.
*/
#define PyMem_Resize(p, type, n) \
( (p) = ((size_t)(n) > PY_SSIZE_T_MAX / sizeof(type)) ? NULL : \
(type *) PyMem_Realloc((p), (n) * sizeof(type)) )
#define PyMem_RESIZE(p, type, n) \
( (p) = ((size_t)(n) > PY_SSIZE_T_MAX / sizeof(type)) ? NULL : \
(type *) PyMem_REALLOC((p), (n) * sizeof(type)) )
/* PyMem{Del,DEL} are left over from ancient days, and shouldn't be used
* anymore. They're just confusing aliases for PyMem_{Free,FREE} now.
*/
#define PyMem_Del PyMem_Free
#define PyMem_DEL PyMem_FREE
- 比如在
PyMem_New中,只需要提供类型和数量,就会自动侦测所需的内存空间大小。
3. 第2层
- 为了简化开发,Python在比第1层更高的抽象层次上提供了第2层内存管理接口。
- 在这一层,是一组以
PyObje_为前缀的函数族,主要提供了创建Python对象的接口。 - 这一套函数族又称作Pymalloc机制。
- 第2层是真正在Python中发挥巨大作用的一层内存管理机制,同时也是GC的藏身之处,后面我们会深入剖析这层。
4. 第3层
- 在第2层的管理机制上,Python又对一些常用对象,比如int对象,string对象等构建了更高抽象层次的内存管理策略。
- 对于第3层的内存管理策略,主要就是对象缓冲池机制,这个在大师兄的Python源码学习笔记(四): 字符串对象中已经介绍过了。
