赞
踩
本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie
1.内存管理架构
Python的内存管理机制都有两套实现:debug模式和release模式
Python内存管理机制的层次结构:
第0层是操作系统提供的内存管理接口,如malloc、free
第1层是Python基于第0层操作系统的内存管理接口包装而成的,主要是为了处理与平台相关的内存分配行为。
实现是一组以PyMem_为前缀的函数族
两套接口:函数和宏。
宏,可以避免函数调用的开销,提高效率,但可能与新版本的python产生二进制不兼容,如果用C来编写Python的
扩展模块,使用函数接口是一个良好的编程习惯
第2层 以PyObje_为前缀的函数族,主要提供创建Python对象的接口。包括了gc内存管理机制
第3层 对象缓冲池机制
2.小块空间的内存池
Pymalloc机制:内存池机制,管理对小块内存的申请和释放,通过PyObject_Malloc、PyObject_Realloc、PyObject_Free
三个接口显示给Python
整个小块内存的内存池可以视为一个层次结构,分为4层,从下至上分别是:block,pool,arena和内存池
Block
所有block的长度都是8字节对齐的(ALIGNMENT)
SMALL_REQUEST_THRESHOLD:当申请的内存小于这个值时,Python可以使用不同种类的block来满足对内存
的需求;当申请的内存大小超过这个上限,转交请求给第一层内存管理机制。
根据 SMALL_REQUEST_THRESHOLD和 ALIGNMENT的限定,可以得到以下结论:
图
- //从size class index转换到size class
- #define INDEX2SIZE(I) (((uint)(I) + 1) << ALIGNMENT_SHIFT)
- //从size class到size class index
- size = (uint )(nbytes - 1) >> ALIGNMENT_SHIFT;
- typedef uchar block;
-
- struct pool_header{
- union{ block *_padding;
- uint count;} ref; //count表示已经分配的block数目
- block *freeblock; //指向下一个可用 block
- struct pool_header *nextpool; //链接下一个pool
- struct pool_header *prevpool; //链接上一个pool
- uint arenaindex;
- uint szidx; //block 大小的index
- uint nextoffset; //指向 freeblock之后的下一个可用的block
- uint maxnextoffset; //指向了pool中最后一个可用的block距pool开始位置的偏移
- };
- #define ROUNDUP(x) (((x) + ALIGNMENT_MASK) & ~ALIGNMENT_MASK)
- #define POOL_OVERHEAD ROUNDUP(sizeof(struct pool_header))
- #define struct pool_header *poolp
- #define uchar block
- poolp pool;
- block *bp;
- //pool指向了一块4KB的内存
- pool->ref.count = 1;
- //设置pool的size class index
- pool->szidx = size;
- //将size class index转换为size,比如3转换为32字节
- size = INDEX2SIZE(size);
- //跳过用于pool_header的内存,并进行对齐
- bp = (block *)pool + POOL_OVERHEAD;
- //实际就是pool->nextoffset = POOL_OVERHEAD+size + size
- pool->nextoffset = POOL_OVERHEAD + (size << 1);
- pool->maxnextoffset = POOL_size - size;
- pool->freeblock = bp + size;
- if(pool != pool->nextpool){ ++pool->ref.count;
- bp = pool->freeblock;
- //...
- if(pool->nextoffset <= pool->maxnextoffset){
- //有足够的空间
- pool->freeblock = (block *) pool + pool->nextoffset;
- pool->nextoffset += INDEX2SIZE(size);
- *(block **)(pool->freeblock) = NULL; //建立离散自由block链表的关键所在
- return (void *)bp;
- }
- }
- #define POOL_ADDR(P) ((poolp)((uptr)(p) & ~(uptr)POOL_SIZE_MASK))
-
- void PyObject_Free(void *p){
- poolp pool;
- block *lastfree;
- poolp next, prev;
- uint size;
-
- pool = POOL_ADDR(p);
- //判断p指向的block是否属于pool
- if(Py_ADDRESS_IN_RANGE(p, pool)){
- *(block **)p = lastfree = pool->freeblock;//[1]
- pool->freeblock = (block *)p;
- //...
- }
- }
- typedef uchar block;
-
- struct arena_object{
- uptr address;
- block *pool_address;
- uint nfreepools;
- uint ntotalpools;
- struct pool_header *freepools;
- struct arena_object *nextarena;
- struct arena_object *prevarena;
- }
- //arenas管理着arena_object的集合
- static struct arena_object *arenas = NULL;
- //当前arenas中管理的 arena_object的个数
- static uint maxarenas = 0;
- //"未使用"的 arena_object链表
- static struct arena_object *unused_arena_objects = NULL;
- //”可用“ 的 arena_object链表
- static struct arena_object *usable_arenas = NULL;
- //初始化时需主持 arena_object的个数
- #define INITIAL_ARENA_OBJECTS 16
-
-
- static struct arena_object *new_arena(void){
- struct arena_object *arenaobj;
- uint excess;
-
- //[1]:判断是否需要扩充”未使用“的 arena_object列表
- if(unused_arena_objects == NULL){
- uint i;
- uint numarenas;
- size_t nbytes;
-
- //[2]:确定本次需要申请的 arena_object的个数,并申请内存
- numarenas = maxarenas ? maxarenas << 1 : INITIAL_ARENA_OBJECTS;
- if(numarenas <= maxarenas)
- return NULL; //溢出
- nbytes = numarenas * sizeof(*arenas);
- if(nbytes / sizeof(*arenas) != numarenas)
- return NULL; //溢出
- arenaobj = (struct arena_object *)realloc(arenas, nbytes);
- if(arenaobj == NULL)
- return NULL;
- arenas = arenaobj;
-
- //[3]:初始化新申请的 arena_object,并将其放入 unused_arena_objects链表中
- for(i = maxarrenas; i < numarenas; ++i){
- arenas[i].address = 0; //mark as unassociated
- arenas[i].nextarena = i < numarenas - 1 ? &arenas[i + 1] : NULL;
- }
- //update globals
- unused_arena_objects = &arenas[maxarenas];
- maxarenas = numarenas;
- }
-
- //[4]:从 unused_arena_objects 链表中取出一个“未使用”的arena_object
- arenaobj = unused_arena_objects;
- unused_arena_objects = arenaobj->nextarena;
- assert(arenaobj->address == 0);
-
- //[5]:申请arena_object管理的内存
- arenaobj->address = (uptr)malloc(ARENA_SIZE);
- ++narenas_currently_allocated;
-
- //[6]:设置pool集合的相关信息
- arenaobj->freepools = NULL;
- arenaobj->pool_address = (block *)arenaobj->address;
- arenaobj->nfreepools = ARENA_SIZE / POOL_SIZE;
- //将pool的起始地址调整为系统页的边界
- excess = (uint)(arenaobj->address & POOL_SIZE_MASK);
- if(excess != 0){
- --arenaobj->nfreepools;
- arenaobj->pool_address += POOL_SIZE - excess;
- }
- arenaobj->ntotalpools = arenaobj->nfreepools;
- return arenaobj;
-
- }
- typedef union _gc_head{
- struct{
- union _gc_head *gc_next;
- union _gc_head *gc_prev;
- int gc_refs;
- } gc;
- long double dummy;
- } PyGc_Head;
- PyObject *PyDict_New(void){
- register dictobject *mp;
- //...
- mp = PyObject_GC_New(dictobject, &PyDict_Type);
- //...
- _PyObject_GC_TRACK(mp);//将创建的container对象链接到了Python中的可收集对象链表中。
- return (PyObject *)mp;
- }
- #define _PyObject_GC_TRACK(0) do { \
- PyGc_Head *g = _Py_AS_GC(0); \
- if(g->gc.gc_refs != _PyObject_GC_UNTRACKED) \
- Py_FatalError("GC object already tracked"); \
- g->gc.gc_refs = _PyGC_REFS_REACHABLE; \
- g->gc.gc_next = _PyGC_generations0;
- g->gc.gc_prev = _PyGC_generations0->gc.gc_prev; \
- g->gc.gc_prev->gc.gc_prev = g;
- _PyGC_generations0->gc.gc_prev = g;\
- } while(0);
-
-
- #define _PyObject_GC_UNTRACK(0) do{
- //...
- }
- struct gc_generation{
- PyGc_Head head;
- int threshold; //最多可容纳的container对象,超出这个值会立刻触发垃圾回收机制
- int count; //已经链接的container对象数目
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。