Python中list的內存分配


1、創建時:

if (numfree) {
    numfree--;
    op = free_list[numfree];
    _Py_NewReference((PyObject *)op);
} else {
    op = PyObject_GC_New(PyListObject, &PyList_Type);
    if (op == NULL)
        return NULL;
}

首先檢查list的緩沖池free_list中是否有可用的list,如果有則直接使用其內存

如果沒有則調用PyObject_GC_New分配新的內存空間

free_list初始大小為空,最大的大小為PyList_MAXFREELIST,默認定義為80

 

2、銷毀時:

static void
list_dealloc(PyListObject *op)
{
    Py_ssize_t i;
    PyObject_GC_UnTrack(op);
    Py_TRASHCAN_SAFE_BEGIN(op)
    if (op->ob_item != NULL) {
        i = Py_SIZE(op);
        while (--i >= 0) {
            Py_XDECREF(op->ob_item[i]);
        }
        PyMem_FREE(op->ob_item);
    }
    if (numfree < PyList_MAXFREELIST && PyList_CheckExact(op))
        free_list[numfree++] = op;
    else
        Py_TYPE(op)->tp_free((PyObject *)op);
    Py_TRASHCAN_SAFE_END(op)
}

銷毀時,首先將所有元素,即ob_item中的所有引用指向-1,然后對ob_item進行free

之后檢查緩沖池是否已經達到上限,如果沒有則不銷毀list,而是將list放進緩沖池中等待下次利用。

如果緩沖池已經達到PyList_MAXFREELIST的上限,則銷毀該list。

 

3、resize時:

對於list中所有會改變其大小的操作,都會觸發list_resize函數

list_resize接收兩個參數,list本身和新的大小

其中,extends設置的新大小為 m + n

pop設置的新大小為Py_SIZE(self) - 1

append設置的新大小為n+1

    if (allocated >= newsize && newsize >= (allocated >> 1)) {
        assert(self->ob_item != NULL || newsize == 0);
        Py_SIZE(self) = newsize;
        return 0;
    }

首先檢查新大小與已分配大小的關系,如果新要求的大小在已分配空間之下並且大於已分配大小的1/2時,則直接改變ob_size,不進行內存調整。

否則,若新要求的大小大於已分配空間則現有空間不夠,若小於已分配空間的一半了則需進行內存優化,所以需要進行內存的重新調整。

為了避免每插入新增一個元素就要重新分配內存導致效率的降低,list的內存分配采用跳躍式增長

    new_allocated = (newsize >> 3) + (newsize < 9 ? 3 : 6);

    /* check for integer overflow */
    if (new_allocated > PY_SIZE_MAX - newsize) {
        PyErr_NoMemory();
        return -1;
    } else {
        new_allocated += newsize;
    }

及新分配的空間為 新大小 + 新大小的1/8 + 3(新大小小於9)否則為6

及這個'跳躍'的高度由newsize的大小決定,容量越大,增長的也越大。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM