zoukankan      html  css  js  c++  java
  • 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的大小决定,容量越大,增长的也越大。

  • 相关阅读:
    转:10+年程序员总结的20+条经验教训
    年损失超20亿,手游行业第三方安全服务需求迫切
    分享:Android 应用有哪些常见,浅谈常被利用的安全漏洞?
    Android手机开发(一)
    分享:不懂技术,不要对懂技术的人说这很容易实现
    spring-boot学习六:外部配置加载顺序
    spring-boot学习五:Spring boot配置文件的加载位置
    spring-boot学习一:使用Spring Initializr快速创建Spring boot项目
    数值比较有说头
    常见SQL积累
  • 原文地址:https://www.cnblogs.com/ruizhang3/p/6823470.html
Copyright © 2011-2022 走看看