上篇文章CPython源码阅读-基础6 说到最简单的对象浮点对象的创建,我们可以感觉到,这种对象创建和销毁应该是非常频繁的。如果每次创建都申请内存空间,每次销毁都回收内存空间的话,那Python的效率应该会更低的。CPython内部目前的做法是,在操作系统之上,封装一个空闲对象内存缓冲池。
具体的做法是,Python在浮点对象销毁后,不是直接将内存回收,而是将要销毁的空间浮点对象放入一个空闲链表。后续需要创建浮点对象时,直接在空闲链表中取,提高效率,不用每次都分配内存。新的浮点数对象,从新初始化对应成员即可。Python中其他对象也有对应的空闲对象缓冲池。
# define PyFloat_MAXFREELIST 100
//要销毁的浮点对象放入空闲对象缓冲池的最大个数
struct _Py_float_state {
/* Special free list
free_list is a singly-linked list of available PyFloatObjects,
linked via abuse of their ob_type members. */
int numfree;
//当前空闲对象缓冲池已经存在的浮点对象的数量
PyFloatObject *free_list;
//指向链表头结点的指针
};
这个内存池中的链表的通过内部的ob_type指针指向下一个对象的。
回过头再看,PyFloat_FromDouble,就是从内存池拿东西。
cpython-master\Objects\floatobject.c
PyObject *
PyFloat_FromDouble(double fval)
{
struct _Py_float_state *state = get_float_state();
PyFloatObject *op = state->free_list;
if (op != NULL) {
#ifdef Py_DEBUG
// PyFloat_FromDouble() must not be called after _PyFloat_Fini()
assert(state->numfree != -1);
#endif
state->free_list = (PyFloatObject *) Py_TYPE(op);
state->numfree--;
}
else {
op = PyObject_Malloc(sizeof(PyFloatObject));
if (!op) {
return PyErr_NoMemory();
}
}
_PyObject_Init((PyObject*)op, &PyFloat_Type);
op->ob_fval = fval;
return (PyObject *) op;
}
float_dealloc 就是把空闲待销毁的对象放入内存池。
static void
float_dealloc(PyFloatObject *op)
{
if (PyFloat_CheckExact(op)) {
struct _Py_float_state *state = get_float_state();
#ifdef Py_DEBUG
// float_dealloc() must not be called after _PyFloat_Fini()
assert(state->numfree != -1);
#endif
if (state->numfree >= PyFloat_MAXFREELIST) {
PyObject_FREE(op);
return;
}
state->numfree++;
Py_SET_TYPE(op, (PyTypeObject *)state->free_list);
state->free_list = op;
}
else {
Py_TYPE(op)->tp_free((PyObject *)op);
}
}