(图片来自: https://nodefe.com/implement-of-pymalloc-from-source/)
arena、pool和block
Python的对象分配器将内存分为三个维度,从大到小叫做arena、pool以及blcok。
arena
一个arena分为两个部分。管理部分arena_object,每次需要创建一个arena时,先创建一个arena_object结构放入arenas数组。然后再申请256KB内存作为arena管理的内存部分。arena_object和arena的内存是分开的,通过域address标记。
pool
将arena的内存按照4KB再划分则为一个个pool。每个pool也分为两部分,内存的高端为pool_header用于管理分配出去的block、回收的block以及从来没有被分配出去的block;剩余的内存作为另一部分再被分为一个个block。每个pool一旦使用只能分配固定个数的block。pool的两部分在同一个连续的页内。
pool会有三种状态:
used: 部分block被分配出去,另一部分还未被分配出去。该状态的pool会被放入usedpools中以加快搜寻可用pool的速度。如果used的pool中的最后的block也被分配出去则pool进入full状态,并且从usedpool中去掉。如果used的pool中的block全被回收则pool进入empty状态,并且从usedpool中去掉放入arena中的freepools链表中。
empy: 所有的block都没有被分配出去。有两种可能,一种是pool中的block都被回收了,从used状态转变而来,这样的pool放入arena的freepools链表中;另外一种是随着arena初始化而来,此时还没有作为pool存在,只是作为arena中没有被使用的内存部分。
full: 所有的block被分配出去了。不存在任何链表中,当有block被回收时进入used状态再放入usedpool中。
block
block是内存管理的最小单位,每次分配需要按照block对齐。每次分配和回收都是固定个数的block。当内存被回收时,所有的内存会放入pool中的链表freeblocks中。没有被分配出去的block存在两个地方,一部分从来没有被分配出去过,通过nextofset表明空闲的block的起始地址;另一部分是分配出去又被回收,会被放入freeblocks中。
被回收的block会将头部作为指针链接下一个被回收的block
|
|
pool的种类
按照每次可以分配的block的个数,pool被分为几种类型(block size),同时也是其在usedpool中的序号(szidx)。每页为4KB,每个8个block1算作一组,所以pool最多有64个类型。具体可以参见下面代码注释。
python的obmalloc.c源码注释
Objects/obmalloc.c
|
|