CPython内存分配

CPython内存分配,python,memory-management,cpython,Python,Memory Management,Cpython,这篇文章的灵感来自于关于如何为CPython中的对象分配内存。最初,这是在创建列表并在for循环中附加到列表的上下文中,而不是在列表理解中 下面是我的问题: CPython中有多少不同的分配器? 它们各自的功能是什么 何时调用mallocacutally?(列表理解可能不会导致调用malloc,这取决于 python在启动时为自己分配了多少内存? 是否有规则来管理哪些数据结构首先在这个内存上获得“DIB” 当一个对象被删除时,它所使用的内存会发生什么变化(python是否仍然保留内存以在将

这篇文章的灵感来自于关于如何为CPython中的对象分配内存。最初,这是在创建列表并在for循环中附加到列表的上下文中,而不是在列表理解中

下面是我的问题:

  • CPython中有多少不同的分配器?
    • 它们各自的功能是什么
  • 何时调用
    malloc
    acutally?(列表理解可能不会导致调用
    malloc
    ,这取决于
  • python在启动时为自己分配了多少内存?
  • 是否有规则来管理哪些数据结构首先在这个内存上获得“DIB”
  • 当一个对象被删除时,它所使用的内存会发生什么变化(python是否仍然保留内存以在将来分配给另一个对象,或者GC是否会释放内存以供另一个进程使用,比如Google Chrome)
  • GC何时触发
  • list
    s是动态数组,这意味着它们需要一个连续的内存块。这意味着,如果我试图将一个对象附加到一个列表中,而该列表的底层C-data-structure数组无法扩展,那么该数组将被复制到内存的另一个部分,其中有一个更大的连续块可用。那么,在o初始化列表时是否使用此数组?
    • 为新数组分配了多少额外空间,新数组现在保存旧列表和附加对象

  • 编辑:从评论中,我发现这里的问题太多了。我之所以这样做,是因为这些问题都非常相关。不过,如果是这样的话,我很乐意将其分成几个帖子(请在评论中告诉我这样做)

    C API文档的一章回答了大部分问题

    有些文档比您要求的更模糊。要了解更多详细信息,您必须查阅源代码。除非您选择一个特定的版本,否则没有人愿意这样做。(至少2.7.5、2.7.6之前、3.3.2、3.3.3之前和3.4之前的版本对不同的人会感兴趣。)

    文件的源代码是许多问题的良好起点,顶部的注释有一个漂亮的小ASCII艺术图:

        Object-specific allocators
        _____   ______   ______       ________
       [ int ] [ dict ] [ list ] ... [ string ]       Python core         |
    +3 | <----- Object-specific memory -----> | <-- Non-object memory --> |
        _______________________________       |                           |
       [   Python`s object allocator   ]      |                           |
    +2 | ####### Object memory ####### | <------ Internal buffers ------> |
        ______________________________________________________________    |
       [          Python`s raw memory allocator (PyMem_ API)          ]   |
    +1 | <----- Python memory (under PyMem manager`s control) ------> |   |
        __________________________________________________________________
       [    Underlying general-purpose allocator (ex: C library malloc)   ]
     0 | <------ Virtual memory allocated for the python process -------> |
    
       =========================================================================
        _______________________________________________________________________
       [                OS-specific Virtual Memory Manager (VMM)               ]
    -1 | <--- Kernel dynamic storage allocation & management (page-based) ---> |
        __________________________________   __________________________________
       [                                  ] [                                  ]
    -2 | <-- Physical memory: ROM/RAM --> | | <-- Secondary storage (swap) --> |
    
    特定于对象的分配器
    _____   ______   ______       ________
    [int][dict][list]…[string]Python核心|
    +3 |  |  |
    _______________________________       |                           |
    [Python的对象分配器]||
    +2、物体记忆|
    ______________________________________________________________    |
    [Python的原始内存分配器(PyMem_uuAPI)]|
    +1 |  |   |
    __________________________________________________________________
    [底层通用分配器(例如:C库malloc)]
    0 |  |
    =========================================================================
    _______________________________________________________________________
    [特定于操作系统的虚拟内存管理器(VMM)]
    -1 |  |
    __________________________________   __________________________________
    [                                  ] [                                  ]
    -2 |  | |  |
    

    CPython中有多少不同的分配器

    根据文档,“几个”。你可以把内置和stdlib类型中的那些加起来,然后再加上一些通用的,如果你真的想要的话。但是我不确定它会告诉你什么。(这将是非常特定于版本的.IIRC,确切的数字甚至在3.3树中也发生了变化,因为有一个关于新型字符串应该使用三个不同分配器还是一个分配器的实验。)


    它们各自的功能是什么

    级别+3的特定于对象的分配器用于值得优化的特定用例。如文档所述:

    例如,整数对象在堆中的管理方式与字符串、元组或字典不同,因为整数意味着不同的存储要求和速度/空间权衡

    在这下面,在+2级(和+1.5级,可能还有+2.5级)有各种通用的支持分配器——至少有一个对象分配器、一个竞技场分配器和一个小的块分配器等等——但除了第一个之外,所有的都是私有的实现细节(这意味着即使对于C-API也是私有的;显然,所有这些都是Python代码私有的)

    下面是原始分配器,其功能是在高级分配器需要时请求操作系统提供更多内存


    什么时候叫malloc acutally

    原始内存分配器(或其堆管理器)应该是唯一调用
    malloc
    (事实上,它甚至不一定调用
    malloc
    ;它可能使用
    mmap
    VirtualAlloc
    之类的函数。但问题是,它是唯一向操作系统请求内存的东西。)Python核心中有一些例外,但它们很少相关

    文档明确指出,高级代码永远不应该尝试在从
    malloc
    获取的内存中操作Python对象

    然而,除了Python对象之外,还有很多stdlib和扩展模块使用
    malloc

    例如,一个1000x1000 int32值的numpy数组不分配100万Python
    int
    s,因此它不必经过
    int
    分配器。相反,它只需
    malloc
    s一个100万C
    int
    s的数组,并在访问它们时根据需要将它们封装在Python对象中


    python在启动时为自己分配了多少内存

    这是特定于平台的,从代码中有点难以理解。但是,当我在64位Mac上启动一个新的
    python3.3
    解释器时,它会启动