CPython内存管理器功能分类

 

CPython源码包的功能分类

此文是按照源码Python3.9来写,其中有些assert语句与一些不必要的宏字段会删除,保留核心的逻辑并添加注释,方便自己和大家理解。在代码中都会注明源码出处方便大家完整阅读。

目录 概要
Demo 采用了Python的演示应用程序
Doc 文档
Grammer Python的语法文件
Include 编译Python时引用的各种头文件
Lib 标准附加库
Mac Mac用的工具等
Misc 很多文件的集合(如gdbinit和vimrc等)
Modules Python的C语言扩展模块
Objects Python的对象用的C语言代码
PC 依存于OS等环境的程序
PCbuild 构造Win32和x64时使用
Parser Python用的解析器
Python Python的核心

Python的内存管理架构

Python是一门动态的、一切皆对象的语言,这些内存申请可能会产生大量小的内存,为了加快内存操作和减少内存碎片化,使用Python自己的内存管理器,叫PyMalloc。


  1. # Objects/obmalloc.c 代码注释  
  2. /* An object allocator for Python.  
  3.    Here is an introduction to the layers of the Python memory architecture,  
  4.    showing where the object allocator is actually used (layer +2), It is  
  5.    called for every object allocation and deallocation (PyObject_New/Del),  
  6.    unless the object-specific allocators implement a proprietary allocation  
  7.    scheme (ex.: ints use a simple free list). This is also the place where  
  8.    the cyclic garbage collector operates selectively on container objects.  
  9.     Object-specific allocators  
  10.     _____   ______   ______       ________  
  11.    [ int ] [ dict ] [ list ] … [ string ]       Python core         |  
  12. +3 | <—– Object-specific memory —–> | < Non-object memory —> |    # 对象特有的内存分配器  
  13.     _______________________________       |                           |  
  14.    [   Python's object allocator   ]      |                           |  
  15. +2 | ####### Object memory ####### | <—— Internal buffers ——> |    # Python对象分配器  
  16.     ______________________________________________________________    |  
  17.    [          Python's raw memory allocator (PyMem_ API)          ]   |  
  18. +1 | <—– Python memory (under PyMem manager's control) ——> |   |      # Python低级内存分配器  
  19.     __________________________________________________________________  
  20.    [    Underlying general-purpose allocator (ex: C library malloc)   ]  
  21.  0 | <—— Virtual memory allocated for the python process ——-> |      # 通用的基础分配器(如glibc的malloc等)                                     
  22.     =========================================================================  
  23.     _______________________________________________________________________  
  24.    [                OS-specific Virtual Memory Manager (VMM)               ]  
  25. -1 | < Kernel dynamic storage allocation & management (page-based) —> |  # OS特有的虚拟内存管理器  
  26.     __________________________________   __________________________________  
  27.    [                                  ] [                                  ]  
  28. -2 | < Physical memory: ROM/RAM —> | | < Secondary storage (swap) —> |  # 物理内存和交换目的地(如HDD等)  
  29. */ 

  1. PyDict_New()               // 第三层  
  2.  PyObject_GC_New()     // 第二层  
  3.   PyObject_Malloc()     // 第二层  
  4.    new_arena()       // 第一层  
  5.    malloc()        // 第零层  
  6. ////////////////////////////////////////以下2层属于操作系统范畴,不在讨论范围///////////////////////////////// 

通用的基础分配器(0层)

512字节是CPython的阈值 


  1. //Objects/obmalloc.c  
  2. #define SMALL_REQUEST_THRESHOLD 512  
  3. #define NB_SMALL_SIZE_CLASSES   (SMALL_REQUEST_THRESHOLD / ALIGNMENT)  
  4. /* Largest positive value of type Py_ssize_t. */  
  5. #define PY_SSIZE_T_MAX ((Py_ssize_t)(((size_t)-1)>>1))  
  6. static void * 
  7.  _PyObject_Malloc(void *ctx, size_t nbytes)  
  8. {  // 走Python的分配器,函数进去就会有判断(0,512]的才使用  
  9.     void* ptr = pymalloc_alloc(ctx, nbytes);  
  10.     if (LIKELY(ptr != NULL)) {  
  11.         return ptr;  
  12.     }  
  13.   // 大于512字节走C的malloc,函数进去进做了越界判断,Py_ssize_t为阈值  
  14.     ptr = PyMem_RawMalloc(nbytes);  
  15.     if (ptr != NULL) {  
  16.         raw_allocated_blocks++;  
  17.     }  
  18.     return ptr;  
  •  0: 直接调用 malloc 函数
  •  1 ~ 512: 由Python的内存池负责分配,内存池以内存尺寸进行划分
  •  512以上: 直接调动 malloc 函数

在源代码中以PyMem_为前缀的所有函数是封装C语言提供给Python语法使用的,其核心使用的就是第0层malloc之类的C库函数。

通常Python没有对小块内存的内存池的大小做任何的限制

当Python在WITH_MEMORY_LIMITS编译符号打开的背景下进行编译时,Python内部的另一个符号会被激活,这个名为SMALL_MEMORY_LIMIT的符号限制了整个内存池的大小,同时,也就限制了可以创建的arena的个数。

在默认情况下,不论是Win32平台,还是unix平台,这个编译符号都是没有打开的,所以通常Python都没有对小块内存的内存池的大小做任何的限制。

【声明】:芜湖站长网内容转载自互联网,其相关言论仅代表作者个人观点绝非权威,不代表本站立场。如您发现内容存在版权问题,请提交相关链接至邮箱:bqsm@foxmail.com,我们将及时予以处理。

相关文章