pg的内存管理机制三:AllocSet/MemoryContext实例删除和内存回收

 

话说 MemoryContextMethods 结构里的函数实现了pgAllocSet/MemoryContext 的内存管理机制,定义见下面。

typedef struct MemoryContextMethods

{

     void    *(*alloc) (MemoryContext context, Size size);

     /* call this free_p in case someone #define's free() */

     void      (* free_p ) (MemoryContext context, void *pointer);

     void    *(*realloc) (MemoryContext context, void *pointer, Size size);

     void      (*init) (MemoryContext context);

     void      (*reset) (MemoryContext context);

     void      (*delete ) (MemoryContext context);

     Size     (*get_chunk_space) (MemoryContext context, void *pointer);

     bool      (*is_empty) (MemoryContext context);

     void      (*stats) (MemoryContext context);

#ifdef MEMORY_CONTEXT_CHECKING

     void      (*check) (MemoryContext context);

#endif

} MemoryContextMethods;

 

其中deleteAllocSet 的静态函数 AllocSetDelete () 实现,具体签名在下面。它实现了AllocSet 相关的内存删除机制。而MemoryContext 即父类的内存删除由MemoryContextDelete() 实现,签名在下面。这两个方法各自负责本类型中成员的内存删除工作,好像协作,完成了AllocSet/MemoryContext 类型对象的删除和内存回收工作。

static void AllocSetDelete(MemoryContext context)

void MemoryContextDelete(MemoryContext context)

 

下面就写 MemoryContextMethods.delete 的实现者负责AllocSet 实例删除的AllocSetDelete() 这个函数以及相关的负责MemoryContext 实例删除的MemoryContextDelete() 方法。先上图,然后分块解读处理流程。

 


AllocSet/MemoryContext 实例内存删除流程图

 

    先说红色框吧,在红色框部分,MemoryContextDelete 方法检查要删除的context 是否有效,然后调用MemoryContextDeleteChildren 方法,检查contextfirstchild 是否不为空,若不空就以firstchild 指向的子context 为参数调用MemoryContextDelete 方法。这样就以MemoryContextDelete 方法和MemoryContextDeleteChildren 方法形成了递归调用,以删除当前的context 及它的子context

    接着看黄色框,在前面形成递归调用的基础上,黄色框中主要是删除context 及其子contextnextchild 指向的子context

    再接着看蓝色框,主要是在前面形成递归调用的基础上,针对要删除的context 及其子context 调用AllocSetDelelte 方法,处理contextasetblocks 成员,把aset 置空,把AllocBlock 列表blocks 中的block 使用过的内存空间逐个置0X7F ,然后调free 释放。这个blocks 链表处理完后就到了绿色框中。

    现在看绿色框和紫色框,在绿色框中,还是在前面形成递归调用的基础上,在绿色框中检查要删除的context 的有效性,然后找到该context 所在的AllockChunk 类型实例chunk ,根据该chunk 找到其所属的context ,把要删除的context 和其所在的chunk 所属的context 一起作为参数调用AllocSetFree 方法去释放要删除的context 所占内存。AllocSetFree 释放内存在 pg 的内存管理机制二 》中已经讨论过了,感兴趣可以去看一下。

这样就在以MemoryContextDelete 方法和MemoryContextDeleteChildren 方法形成的递归调用里逐个删除要删除的context 及其firstchildnextchild 成员“链”上的context 。具体看流程图吧。

结合图形看一个递归删除MemoryContext 类型实例时的顺序的例子,图中一个圆圈代表一个MemoryContext 类型实例,在左下方的是MemoryContextfirstshild 成员,在右下方的是nextchild 成员。图一是初始时的样子,现在要删除节点4 ,先顺着4firstchild 递归到其最终叶子节点6 ,将其按上面说的过程删除并释放空间,如图二。然后将节点4nextchild 节点7 放到4 的父节点3nextchild 子节点上,把节点3 原来的nextchild 子节点5 放到节点7nenxtchild 子节点上,如图三。这时已经处理完了节点4 的两个子节点,将节点4 删除。

 

 

 

 

就到这儿吧。

猜你喜欢

转载自beigang.iteye.com/blog/1320162