pg源码阅读四

本文深入探讨了 PostgreSQL 中的内存管理,尤其是内存上下文的概念。内存上下文分为不同类型,如默认、顶层和错误上下文等。MemoryContextSwitchTo() 函数用于在上下文之间切换。在系统初始化时,通过 MemoryContextInit 创建和初始化内存上下文,如 TopMemoryContext 和 ErrorContext。AllocSetContextCreate 和 MemoryContextCreate 负责上下文的创建,维护了一个由 AllocBlock 指针链接的内存块链表,以高效地分配和管理内存。
摘要由CSDN通过智能技术生成

pg中的内存是内存上下文来管理的,有不同类型的上下文,不同的上下文是通过MemoryContextMethods指针操作的,下面的是顶层的上下文
MemoryContext CurrentMemoryContext = NULL;默认的上下文
MemoryContext TopMemoryContext = NULL;
MemoryContext ErrorContext = NULL;
MemoryContext PostmasterContext = NULL;
MemoryContext CacheMemoryContext = NULL;
MemoryContext MessageContext = NULL;
MemoryContext TopTransactionContext = NULL;
MemoryContext CurTransactionContext = NULL;

使用The MemoryContextSwitchTo()
operation selects a new current context (and returns the previous context,
so that the caller can restore the previous context before exiting).
能切换到新的上下文中并保留之前的上下文
在postmaster初始化的时候调用MemoryContextInit
* In normal multi-backend operation, this is called once during
* postmaster startup, and not at all by individual backend startup

在入口main函数中使用MemoryContextInit();来创建内存上下文,这个方法会初始化TopMemoryContext and ErrorContext

在MemoryContextInit中使用下马的方法分配上下文
TopMemoryContext = AllocSetContextCreate((MemoryContext) NULL,
“TopMemoryContext”,
0,
8 * 1024,
8 * 1024);

在AllocSetContextCreate中使用MemoryContextCreate创建一个上下文,AlocSet 是一个指向AllocSetContext的指针,这个是实际的返回的上下文,这个方法只是创建了一个节点
context = (AllocSet) MemoryContextCreate(T_AllocSetContext,
sizeof(AllocSetContext),
&AllocSetMethods,
parent,
name);
在创建节点后,然后初始化这个节点的分配参数,比如,初始值,最大值,下一个分配值等。
在MemoryContextCreate中,将返回转成了AllocSet指针

(AllocSet)MemoryContextCreate(NodeTag tag, Size size,
MemoryContextMethods *methods,
MemoryContext parent,
const char *name)
在这个函数中使用node = (MemoryContext) malloc(needed);分配了节点的空间,然后配置了节点的信息主要是添加到上下文二叉树中最左边
if (parent)
{
node->parent = parent;
node->nextchild = parent->firstchild;
parent->firstchild = node;
}

在节点创建完成后,在分配下这个上下文节点的空间
Size blksize = MAXALIGN(minContextSize);
AllocBlock block;

    block = (AllocBlock) malloc(blksize);
    if (block == NULL)
    {
        MemoryContextStats(TopMemoryContext);
        ereport(ERROR,
                (errcode(ERRCODE_OUT_OF_MEMORY),
                 errmsg("out of memory"),
                 errdetail("Failed while creating memory context \"%s\".",
                           name)));
    }
    block->aset = context;
    block->freeptr = ((char *) block) + ALLOC_BLOCKHDRSZ;
    block->endptr = ((char *) block) + blksize;
    block->next = context->blocks;
    context->blocks = block;
    /* Mark block as not to be released at reset time */
    context->keeper = block;

在之后就可以在这内存上下文中进行内存的分配,回收了,下面是一些相关的数据结构,上下文的内存是通过AllocBlock指针进行链接的。

typedef struct AllocSetContext
{
MemoryContextData header; /* Standard memory-context fields */
/* Info about storage allocated in this context: */
AllocBlock blocks; /* head of list of blocks in this set */
AllocChunk freelist[ALLOCSET_NUM_FREELISTS]; /* free chunk lists */
bool isReset; /* T = no space alloced since last reset */
/* Allocation parameters for this context: */
Size initBlockSize; /* initial block size */
Size maxBlockSize; /* maximum block size */
Size nextBlockSize; /* next block size to allocate */
Size allocChunkLimit; /* effective chunk size limit */
AllocBlock keeper; /* if not NULL, keep this block over resets */
} AllocSetContext;
上面的blocks是一个指向所有内存链表开始的指针,freelist是空闲内存数组,这里面说是每个元素保存了一定尺寸大小空闲内存,这个跟oracle差不多,为了能分配给请求合适大小的内存,提高分配效率。具体代码没看到,待需要在看
typedef AllocSetContext *AllocSet;
typedef struct AllocBlockData *AllocBlock;
typedef struct AllocChunkData *AllocChunk;
struct AllocBlockData
{
AllocSet aset; /* aset that owns this block */
AllocBlock next; /* next block in aset’s blocks list */
char freeptr; / start of free space in this block */
char endptr; / end of space in this block */
} AllocBlockData;
在main中分配了顶层的内存上下文,到postmaster中,我们看到使用了下面的方式分配postmaster的内存上下文
PostmasterContext = AllocSetContextCreate(TopMemoryContext,
“Postmaster”,
ALLOCSET_DEFAULT_MINSIZE,
ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE);

父指向了TopMemoryContext

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值