四时宝库

程序员的知识宝库

CPython源码阅读7-对象的销毁-空闲对象缓冲池

上篇文章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);

}

}

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接