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;

 

其中realloc 由静态函数AllocSetRealloc() 实现,具体签名在下面。它实现了AllocSet/MemoryContext 相关的内存再分配。AllocSetRealloc() 方法 返回按请求大小新分配的内存的指针。把新分配的内存加入到set 中,把传进来的pointer 相关的旧内存里的内容拷贝到新内存里,把旧内存释放掉。新分配的内存有可能是在原来的基础上再在后面加一部分,这样就不用拷贝旧内存内容和释放就内存了。

static void * AllocSetRealloc(MemoryContext context, void *pointer, Size size)

在某个context 里的chunk 的内存不够用的时候,就调用MemoryContextrepalloc() 方法,该方法再调用 AllocSetRealloc() 方法 调整原来分配给AllocChunk 类型实例chunk 的大小。

下面就写 MemoryContextMethods. realloc 的实现者AllocSetRealloc () 这个函数。先上图,然后分块解读处理流程。

 


pg的内存管理机制四:AllocSet/MemoryContext的内存再分配_第1张图片

 

AllocSetFree 回收内存流程图

 

先看红色框,根据传进来了要扩展内存的chunk 和其所在的context ,检查该chunk 原来分配的空间oldsize 和本次请求的空间size ,如果原oldsize 可以满足要求,就把该chunk 的请求大小request_size 置成size ,返回该chunk 。如果oldsize 不能满足本次请求的大小size 。就根据chunk 原来分配的空间oldsize 的是否大于AllocChunk 的大小上限/8k 判断,大于该上限就到黄色框,负责到蓝色框。

接着看黄色框,根据该chunk 找到其所在的block ,以该block 和根据请求的chunk 大小size 换算的AllocBlock 的东西blksize 调用realloc() 方法分配内存,成功就返回对应chunk 的指针,负责写日志报错“out of memory

再接着看蓝色框,检查chunk 是否是其所在block 里的最后一个AllocChunk ,如果是,检查该block 剩余的空间和该chunk 的空间加起来是否满足全球的大小size ,如果可以就在该block 中开展这个chunk ,然后返回该chunk 的指针。负责就到了紫色框。

做后看紫色框,调用AllocSetAlloc() 方法(参见《pg 的内存管理机制一 》)在当前MemoryContext 上分配空间新的空间该chunk ,把chunk 原来内存里的内容拷贝过来,调用AllocSetFree() 释放chunk 原来所占的内存。具体看流程图吧。

 

你可能感兴趣的:(PostgreSQL,内存管理,realloc,内存再分配)