Postgresql内存上下文分析
1 数据库内存上下文postgresql在7.1版本引入了内存上下文机制来解决日益严重的内存泄漏的问题,在引入了这种“内存池”机制后,数据库中的内存分配改为在“内存上下文中”进行,对用户来说,对内存的申请由原来的malloc、free变成了palloc、pfree。对内存上下文的常用操作包括:
这里引入两个概念:内存片和内存块的概念。
2 数据结构2.1 AllocSetContexttypedef 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 */
/* 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;
AllocSetContext是内存上下文的核心的控制结构,我们在代码中经常看到的内存上下文TopMemoryContext的定义为: MemoryContext TopMemoryContext = NULL; 可以看到这个内存上下文的类型是MemoryContext,即: typedef struct MemoryContextData
{
NodeTag type; /* identifies exact 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) */
bool isReset; /* T = no space alloced since last reset */
} MemoryContextData;
那么MemoryContextData和AllocSetContext是什么样的关系呢?请看下图左半部分。 AllocSet set = (AllocSet) context;
由于AllocSetContext结构中的首部存放着MemoryContextData指针,所以这种转换可以成功。这样的使用方法有些类似与类的继承:MemoryContextData代表父类,AllocSetContext在父类(头部的指针)的基础上增加了一些新的功能。实际上PG就是使用了这种机制实现了interface(MemoryContextData作为interface),而后面的实现可以有很多种(AllocSetContext是内存上下文的一种实现)。
MemoryContextData使内存上下文形成了一个二叉树的结构,这样的数据结构增加了内存上下文的易用性,即在重置或删除内存上下文时,所有当前上下文的子节点也会被递归的删除或重置,避免错删或漏删上下文。methods中保存的全部为函数指针,在内存上下文创建时,这些指针会被赋予具体函数地址。
2.2 AllocChunkData内存片存在于内存块以内,是内存块分割后形成的一段空间,内存片空间的头部为AllocChunkData结构体,后面跟着该内存片的空间,实际上palloc返回的就这指向这段空间首地址的指针。内存片有两种状态:AllocSetContext中freelist数组中存放的是内存片指针是被回收的内存片;另外一种内存片是用户正在使用的内存片。(注意两种状态的内存片都存在于内存块中,被回收只是改变内存片aset指针,形成链表保存在freelist中;在使用中的内存片aset指针指向所属的AllocSetContext) typedef struct AllocChunkData
{
void *aset;
Size size;
} AllocChunkData;
在palloc时会发生两种情况:
内存片的数据结构相对简单,空指针aset是一个复用的指针,当内存片正在使用时,aset指向它属于的allocset结构,当内存片被释放后,内存片被freelist数组回收,aset作为实现链表的指针,用于形成内存片的链式结构。 2.3 AllocBlockDatatypedef 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;
内存块是内存上下文向操作系统申请的连续的一块内存空间,申请后将AllocBlockData结构置于空间的首部,其中freeptr和endptr用与指向当前内存块中空闲空间的首地址和当前内存块的尾地址,见图2-1中的“连续内存段(内存块)”。aset指向控制结构AllocSetContext,next指针形成内存块的链式结构。 2.4 freelist[ALLOCSET_NUM_FREELISTS]AllocSetContext结构中的一个重要的数组freelist,这是一个定长数组: #define ALLOCSET_NUM_FREELISTS 11
.
.
AllocChunk freelist[ALLOCSET_NUM_FREELISTS]; /* free chunk lists */
.
.
这是一个存放内存片指针的数组,数组中每一个元素都是一个内存片指针,就像前面提到的,空闲内存片会形成链表结构,而链表的头结点的指针就存放在这个数组中。从长度来看,这个数组可以保存11个内存片的链表,每一个链表都保存这特定大小的内存片: 图2-2描述的就是freelist数组的结构,数组下标0位置保存8字节的内存片,下标1位置保存16字节的内存片,以此类推,freelist中可以保存的最大的内存片为8k字节。 3 算法3.1 AllocSetContextCreate:创建内存上下文MemoryContext
AllocSetContextCreate(MemoryContext parent,const char *name,Size minContextSize,Size initBlockSize,Size maxBlockSize)
内存上下文创建需要传入几个参数:
让我们看几个数据库中最常见的上下文创建时的参数,结合具体值在说说创建时参数的作用:
3.2 AllocSetAlloc申请内存的流程图: 需要重点关注的有几点:
3.3 AllocSetFree释放内存流程图: 3.4 AllocSetReallocrelloc流程图: 3.5 AllocSetStats这个函数会被MemoryContextStats递归调用,遍历内存上下文树的内个节点,并获取当前节点的信息。 GDB调试时这一个非常好用的函数,可以直接在log中打印内存上下文树,指令: gdb > p MemoryContextStats(TopMemoryContext)
关于PG数据库GDB的一些调试技巧在下篇博客中继续介绍。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- flex解决用image加载swf文件后页面异常放大的问题
- Unity3D研究院之将场景导出XML或JSON或二进制并且解析还原场
- 深入解析C++的WNDCLASS结构体及其在Windows中的应用
- applicationContext.xml文件中class中的内容不能提示
- 如何确定哪些对象保存对在目标c中引起内存泄漏的其他对象的
- oracle 11g exp 报错 EXP-00056;ORA-12154;EXP-00000;
- sprite-kit – 调整文本大小以适合具有固定宽度的SKLabelNo
- XML Condition And
- c – 如何正确转发unique_ptr?
- 详解vue与后端数据交互(ajax):vue-resource