接上文:
2.1 arean
多个pool聚合起来就是arean了,当然它也有默认的大小,一般是256k,包含的poo的个数就是256 / 4 = 64 个
先看下arean:
struct arena_object {
uptr address;
block* pool_address;
uint nfreepools;
uint ntotalpools;
struct pool_header* freepools;
struct arena_object* nextarena;
struct arena_object* prevarena;
};
在概念上其实就是一个结构体:
未使用的arena:arean_object构成的集合会成为一个数组,数组的首地址有arean来维护,这个数组就是py中
通用小块内存的内存池,另一方面nextarea和prearea是用来连接arean_object来形成链表结构的,arena用来
管理一组pool,
与pool管理block是类似的,不同的是,pool_header管理的内存是和pool_header连接在一起
areana_object和它管理的内存却是分离的,当pool_header被申请时,它所管理的内存block集合也会一起
被申请,而areana_object被申请时,pool集合的内存却没有被申请,也就是在某一时刻,pool和sreana才
会建立联系,arean从未使用状态变为可用状态,可用状态和不可用状态分别维护自己的arena链表,未使用
状态的链表是单向链表,可用状态的链表是一个双向链表,使用new_arena来申请,这就是那个arena
完整的pool包含pool_header和blocks,arena也包含 arena_object和arena_object所包含的
pool集合,在创建新的arena时,py会先检查是否还有未使用状态的arena,如果有,从中抽取一个,把申请
的内存地址赋值给arena的address,申请到的这256k的内存大小就是pool的容身之处,,这是arena就
和pool建立了联系,脱离了未使用态,py还对申请到的256k的内存大小做了处理,使其是边界对齐的,把pool
集合交给pool_address来管理,实际上所有arena的集合就是小块内存池,但py操作内存的最小单元却是pool
一个arena中的pull总是处于下边三种状态中的一种:
1)used状态:至少有一个pool处于使用状态,至少一个pool处于未使用状态,内部维护了一个usedpool数组
2)full状态:pool中所有的block都已经被使用完毕
3)empty状态:pool中所有的block都未被使用,处于这个状态的pool的集合通过pool_header中的next_pool构成一个链表,这个链表的表头就是arena_object中的freepools
注意:full状态的pool是相互独立的,并没有形成链表
2.2 缓冲池
PyObject_Malloc会在内存池中申请内存,当申请的内存大于256k时,PyObject_Malloc会变成真正的malloc,当然,可以通过修改python的源码来修改这个默认值
2.2.1 pool的初始化
在python启动的时候,usedpools这个小块空间内存池并不存在可用内存,py采用了延迟分配的策略,申请内存时才建立这个内存池,例如申请28字节的内存大小,py会先在usedpools对应位置查找,查找不到任何可用的pool时,py会从unused_arenas中的第一个可用arena获取一个pool,而如果此时usable_arenas为空的话,py会新申请一个arena
PS: 写的比较简略,希望有兴趣的读者去看下Python源码剖析这本书,pdf版,you can get :
哈哈~ 希望可以帮到大家