微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

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

typedef structMemoryContextMethods

{

void *(*alloc) (MemoryContext context,Sizesize);

/* 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;

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

static void AllocSetDelete(MemoryContextcontext)

void MemoryContextDelete(MemoryContext context)

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


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

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

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

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

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

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

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


就到这儿吧。

原文地址:https://www.jb51.cc/postgresql/196746.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐