PostgreSQL内存上下文

内存管理体系结构

在这里插入图片描述

内存上下文

内存上下文(MemoryContext)借鉴了操作系统的一些概念。

操作系统为每个进程分配了进程执行环境,进程之间互不影响,由操作系统来对环境进行切换,进程可以在其进程环境中调用内存操作函数:malloc、free、realloc等。

类似的,一个内存上下文实际上相当于一个进程环境,PostgreSQL以类似的方式提供了在内存上下文进行内存操作的函数:palloc、pfree、repalloc等。

每个进程/线程有多个私有的内存上下文,组成上下文树。

内存上下文树

在这里插入图片描述

  • 每个线程都有多个内存上上下文,组成树形结构。线程所有的内存操作都在各种语义的上下文中进行。
  • 释放上下文节点会释放其所有的子节点。
  • 线程退出时释放TopMemoryContext。

术语

  • MemoryContext
  • AllocSetContext
  • Block
  • Chunk
  • 超大块
  • Chunk Free List

内存上下文结构

在这里插入图片描述

数据结构

  • MemoryContext
  • MemoryContextMethods
  • AllocSet
  • AllocBlockData
  • AllocChunkData

MemoryContext

typedef struct MemoryContextData
{
    NodeTag       type;         /* identifies exacts kind of context */
    MemoryContextMethods *methods;  /* virtual function table */
    MemoryContext parent;        /* NULL if no parent (toplevel context) */
    MemoryContext firstchild;    /* head of linked list of children */
    MemoryContext nextchild;     /* next child of same parent */
    char         *name;          /* context name (just for debugging) */
} MemoryContextData;

typedef struct MemoryContextData *MemoryContext;

MemoryContext中的methods字段是一个MemoryContextMethods类型,它是由一系列的函数指针组成的集合,其中包含了对内存上下文操作的函数。对不同的MemoryContext实现,可以设置不同的方法集合。目前MemoryContext中只有AllocSetContext一种实现,因此PostgreSQL中只有针对AllocSetContext的一种操作函数集合,由全局变量AllocSetMethods表示。

MemoryContextMethods

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);
    void        (*reuse) (MemoryContext context);
    Size        (*get_chunk_space) (MemoryContext context, void *pointer);
    bool        (*is_empty) (MemoryContext context);
    void        (*stats) (MemoryContext context);
    bool        (*is_realempty)(MemoryContext context);
#ifdef MEMORY_CONTEXT_CHECKING
    void        (*check) (MemoryContext context);
#endif
} MemoryContextMethods;

方法集

static MemoryContextMethods AllocSetMethods = {
    AllocSetAlloc,
    AllocSetFree,
    AllocSetRealloc,
    AllocSetInit,
    AllocSetReset,
    AllocSetDelete,
    AllocSetReuse,
    AllocSetGetChunkSpace,
    AllocSetIsEmpty,
    AllocSetStats,
    AllocSetIsRealEmpty
#ifdef MEMORY_CONTEXT_CHECKING
    ,AllocSetCheck
#endif
};

MemoryContext是一个抽象类,可以有多个实现,目前只有AllocSetContext一个实现。MemoryContext并不管理实际上的内存分配,仅仅用作对MemoryContext树的控制。管理一个内存上下文中的内存块时通过AllocSet结构来完成的,MemoryContext作为AllocSet的头部信息存在。

AllocSet

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 */
    AllocBlock  keeper;        /* if not NULL, keep this block over resets */
} AllocSetContext;

typedef AllocSetContext *AllocSet;

blocks是内存块链表,freelist是内存片链表。AllocSet所管理的内存区域被分成若干个内存块(AllocBlockData结构),每个内存块又被分成多个内存片(AllocChunkData结构)。palloc申请到的内存实际上都是内存片(除了超大块)。

AllocBlockData

typedef 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;

AllocChunkData

typedef struct AllocChunkData
{
    /* aset is the owning aset if allocated, or the freelist link if free */
    void       *aset;
    /* size is always the size of the usable space in the chunk */
    Size        size;
#ifdef MEMORY_CONTEXT_CHECKING
    /* when debugging memory usage, also store actual requested size */
    /* this is zero in a free chunk */
    Size        requested_size;
#endif
} AllocChunkData;

在这里插入图片描述

重要函数

函数功能
MemoryContextCreate创建上下文节点
AllocSetContextCreate创建上下文实例
MemoryContextDelete删除内存上下文
MemoryContextReset重置内存上下文
MemoryContextSwitchTo切换当前上下文
palloc在当前上下文中申请内存
pfree释放内存
repalloc在当前上下文中重新申请内存

总体流程

在这里插入图片描述

palloc流程

在这里插入图片描述

pfree流程

在这里插入图片描述

重要的内存上下文

内存上下文生命周期描述
TopMemoryContextsession根节点
PostmasterContextsessionpostmaster工作上下文
CacheMemoryContextsessionbackend的relcache、catcache等使用
MessageContextsession保存从前端传来的命令以及派生的存储,比如查询计划树和查询分析树
TopTransactionContexttransaction一般保存跨越多个子事务的状态和控制信息
CurTransactionContexttransaction当前事务上下文
内存上下文生命周期描述
PortalContextportal全局变量,指向当前portal
ErrorContextsession错误处理上下文, errstart、errfinish、errmsg等在此分配内存

打印内存上下文树

in smmgr/aset.c, add #include "utils/memutils.h"
in AllocSetContextCreate function, add

fprintf(stderr, "pid=%d, Create Memory Context name is %s, parent context is %s\n",
		MyProcPid, name, (parent == NULL ? "null" : parent->name));

in mmgr/mcxt.c, add #include "miscadmin.h"
in MemoryContextDelete function, add

fprintf(stderr, "pid=%d, delete memory context name is %s, parent is %s\n",
		MyProcPid, context->name, (context->parent == NULL? 'null' : context->parent->name));

in MemoryContextReset function, add

fprintf(stderr, "pid=%d, reset memory context name is %s, parent is %s\n",
		MyProcPid, context->name, (context->parent == NULL? 'null' : context->parent->name));

代码结构

src/backend/utils/mmgr/mcxt.c
src/backend/utils/mmgr/aset.c
src/include/utils/memutils.h
src/include/nodes/memnodes.h
  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要查看PostgreSQL的CPU和内存使用情况,可以使用以下方法: 1. 查看CPU占用:使用top命令查看CPU占用情况。可以通过执行命令"ps aux | head -1; ps aux | grep -v PID | sort -rn -k 3 | head"来查看每个进程的CPU占用情况,并找到与PostgreSQL相关的进程。 2. 查询执行的SQL:通过执行命令"su - postgres psql -c 'SELECT procpid, START, now()-START AS lap, current_query FROM (SELECT backendid, pg_stat_get_backend_pid(S.backendid) AS procpid, pg_stat_get_backend_activity_start(S.backendid) AS START, pg_stat_get_backend_activity(S.backendid) AS current_query FROM (SELECT pg_stat_get_backend_idset() AS backendid) AS S) AS S WHERE current_query <> ''<IDLE>'' ORDER BY lap DESC;'"来查找执行SQL的进程。 3. 查看执行计划:在定位到具体的SQL之后,可以使用"EXPLAIN SQL"命令来查看执行计划。 关于内存计算(In-Memory Computing),它是指CPU直接从内存而非硬盘上读取数据,并在内存中对数据进行计算和分析。引入内存计算技术可以消除磁盘IO的消耗,并利用内存随机访问的特性来实现更高效的算法。在数据库中引入内存计算技术可以提供更快的查询和处理速度,同时降低了数据访问的延迟。<span class="em">1</span><span class="em">2</span> #### 引用[.reference_title] - *1* [PostgreSQL 数据库运维问题 查看数据库进程 查看CPU占用过高的SQL](https://blog.csdn.net/qq_35260875/article/details/115829218)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [基于PostgreSQL内存计算引擎,来自Lenovo的设计开发经验](https://download.csdn.net/download/weixin_38636655/15465769)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值