海山数据库(He3DB)源码详解:MemoryContextData及MemoryContextMethods结构体解析
MemoryContextData
结构体的作用
MemoryContextData
是 PostgreSQL 中用于实现内存上下文(Memory Context)的核心结构体。内存上下文是 PostgreSQL 的内存管理机制,用于高效地分配和释放内存,支持嵌套内存上下文,并允许在事务或函数结束时批量释放内存。
其中,main
函数会调用MemoryContextInit
函数初始化全局变量TopMemoryContext
,之后的内存申请基本可以从这个全局变量中获得。
结构体定义:
typedef struct MemoryContextData
{
NodeTag type; /* identifies exact kind of context */
/* these two fields are placed here to minimize alignment wastage: */
bool isReset; /* T = no space alloced since last reset */
bool allowInCritSection; /* allow palloc in critical section */
Size mem_allocated; /* track memory allocated for this context */
const MemoryContextMethods *methods; /* virtual function table */
MemoryContext parent; /* NULL if no parent (toplevel context) */
MemoryContext firstchild; /* head of linked list of children */
MemoryContext prevchild; /* previous child of same parent */
MemoryContext nextchild; /* next child of same parent */
const char *name; /* context name (just for debugging) */
const char *ident; /* context ID if any (just for debugging) */
MemoryContextCallback *reset_cbs; /* list of reset/delete callbacks */
} MemoryContextData;
以下是对 MemoryContextData
结构体及其成员的详细解读:
结构体成员:
1. type
NodeTag type; /* identifies exact kind of context */
- 类型:
NodeTag
- 作用:标识内存上下文的具体类型。
- 说明:PostgreSQL 提供了多种类型的内存上下文实现(如
AllocSetContext
、SlabContext
等)。type
字段用于区分当前上下文的具体实现类型。
2. isReset
bool isReset; /* T = no space alloced since last reset */
- 类型:
bool
- 作用:标记自上次重置(reset)以来是否分配了内存。
- 说明
- 如果自上次调用
MemoryContextReset
以来没有分配内存,则该值为true
。 - 这个字段用于优化内存管理,避免不必要的重置操作。
- 如果自上次调用
3. allowInCritSection
bool allowInCritSection; /* allow palloc in critical section */
- 类型:
bool
- 作用:标记是否允许在关键部分(critical section)中分配内存。
- 说明:
- 关键部分是指不允许中断的代码区域,通常用于确保操作的原子性。
- 如果设置为
true
,则允许在关键部分中使用palloc
等内存分配函数。
4. mem_allocated
Size mem_allocated; /* track memory allocated for this context */
- 类型:
Size
(通常为size_t
) - 作用:跟踪当前上下文分配的内存量。
- 说明:用于统计和调试,帮助监控内存使用情况。
5. methods
const MemoryContextMethods *methods; /* virtual function table */
- 类型:
const MemoryContextMethods*
- 作用:指向内存上下文方法表(virtual function table)。
- 说明:
- 每种内存上下文实现都有自己的方法表,包含用于分配、释放和重置内存的函数指针。
- 这种设计允许通过多态方式调用内存管理操作。
6. parent
MemoryContext parent; /* NULL if no parent (toplevel context) */
- 类型:
MemoryContext
(MemoryContextData*
) - 作用:指向当前内存上下文的父上下文。
- 说明:
- 如果当前上下文是顶层上下文,则
parent
为NULL
。 - 支持嵌套内存上下文的层次结构。
- 如果当前上下文是顶层上下文,则
7. firstchild
MemoryContext firstchild; /* head of linked list of children */
- 类型:
MemoryContext
- 作用:指向当前上下文的第一个子上下文。
- 说明:用于构建子上下文的链表。
8. prevchild
MemoryContext prevchild; /* previous child of same parent */
- 类型:
MemoryContext
- 作用:指向当前上下文的前一个兄弟上下文。
- 说明:用于双向链表结构,支持快速遍历。
9. nextchild
MemoryContext nextchild; /* next child of same parent */
- 类型:
MemoryContext
- 作用:指向当前上下文的下一个兄弟上下文。
- 说明:用于双向链表结构,支持快速遍历。
10. name
const char *name; /* context name (just for debugging) */
- 类型:
const char*
- 作用:内存上下文的名称,仅用于调试。
- 说明:提供上下文的标识信息,便于调试和日志记录。
11. ident
const char *ident; /* context ID if any (just for debugging) */
- 类型:
const char*
- 作用:内存上下文的标识符,仅用于调试。
- 说明:提供额外的上下文标识信息,便于调试和日志记录。
12. reset_cbs
MemoryContextCallback *reset_cbs; /* list of reset/delete callbacks */
- 类型:
MemoryContextCallback*
- 作用:指向重置或删除回调函数的链表。
- 说明:
- 当内存上下文被重置或删除时,会调用这些回调函数。
- 回调函数可以用于清理资源或执行其他必要的操作。
总结
MemoryContextData
是 PostgreSQL 中用于实现内存上下文的核心结构体,支持以下功能:
- 层次结构:通过
parent
、firstchild
、prevchild
和nextchild
构建嵌套的内存上下文树。 - 内存管理:通过
methods
提供多态的内存分配和释放操作。 - 调试支持:通过
name
和ident
提供调试信息。 - 回调机制:通过
reset_cbs
支持重置和删除时的回调函数。
这种设计使得 PostgreSQL 的内存管理机制既灵活又高效,能够适应复杂的内存分配和释放需求。
MemoryContextMethods
结构体的作用
MemoryContextMethods
是 PostgreSQL 中定义的一组函数指针,用于实现内存上下文(MemoryContext
)的具体操作。每个内存上下文类型(如 AllocSetContext
、SlabContext
等)都有自己的实现方式,这些函数指针提供了一种统一的接口,允许通过多态的方式操作不同的内存上下文。
以下是对 MemoryContextMethods
结构体及其成员的详细解读:
1. alloc
void *(*alloc)(MemoryContext context, Size size);
- 类型:函数指针
- 作用:分配指定大小的内存。
- 参数:
context
:当前内存上下文。size
:需要分配的内存大小。
- 返回值:分配的内存地址。
- 说明:这是内存分配的核心函数,类似于标准 C 中的
malloc
。
2. free_p
void (*free_p)(MemoryContext context, void *pointer);
- 类型:函数指针
- 作用:释放指定的内存块。
- 参数:
context
:当前内存上下文。pointer
:需要释放的内存地址。
- 说明:为了避免与标准 C 的
free
函数冲突,这里使用了free_p
作为函数名。
3. realloc
void *(*realloc)(MemoryContext context, void *pointer, Size size);
- 类型:函数指针
- 作用:重新分配指定内存块的大小。
- 参数:
context
:当前内存上下文。pointer
:需要重新分配的内存地址。size
:新的内存大小。
- 返回值:重新分配后的内存地址。
- 说明:类似于标准 C 中的
realloc
,用于调整内存块的大小。
4. reset
void (*reset)(MemoryContext context);
- 类型:函数指针
- 作用:重置内存上下文,释放所有分配的内存。
- 参数:
context
:当前内存上下文。
- 说明:重置操作会释放上下文中所有分配的内存,但不会销毁上下文本身。这在事务或函数结束时非常有用,可以批量释放内存。
5. delete_context
void (*delete_context)(MemoryContext context);
- 类型:函数指针
- 作用:销毁内存上下文及其所有子上下文。
- 参数:
context
:需要销毁的内存上下文。
- 说明:销毁操作会释放上下文及其所有子上下文的内存,并清理相关资源。
6. get_chunk_space
Size (*get_chunk_space)(MemoryContext context, void *pointer);
- 类型:函数指针
- 作用:获取指定内存块的总大小。
- 参数:
context
:当前内存上下文。pointer
:内存块的地址。
- 返回值:内存块的总大小。
- 说明:用于调试和统计,帮助了解内存块的实际占用情况。
7. is_empty
bool (*is_empty)(MemoryContext context);
- 类型:函数指针
- 作用:检查内存上下文是否为空。
- 参数:
context
:当前内存上下文。
- 返回值:如果上下文为空(没有分配的内存),返回
true
。 - 说明:用于检查上下文是否需要清理或是否可以安全地销毁。
8. stats
void (*stats)(MemoryContext context,
MemoryStatsPrintFunc printfunc, void *passthru,
MemoryContextCounters *totals,
bool print_to_stderr);
- 类型:函数指针
- 作用:打印内存上下文的统计信息。
- 参数:
context
:当前内存上下文。printfunc
:打印函数。passthru
:传递给打印函数的参数。totals
:统计信息的汇总。print_to_stderr
:是否将统计信息打印到标准错误输出。
- 说明:用于调试和监控,帮助了解内存上下文的使用情况。
9. check
#ifdef MEMORY_CONTEXT_CHECKING
void (*check)(MemoryContext context);
#endif
- 类型:函数指针
- 作用:检查内存上下文的完整性。
- 参数:
context
:当前内存上下文。
- 说明:仅在启用了内存上下文检查(
MEMORY_CONTEXT_CHECKING
)时定义。用于检测内存泄漏或损坏。
总结
MemoryContextMethods
是一个函数指针集合,定义了内存上下文的基本操作。通过这些函数指针,PostgreSQL 提供了一种统一的接口来操作不同类型的内存上下文,支持以下功能:
- 内存分配和释放:
alloc
、free_p
和realloc
。 - 上下文管理:
reset
和delete_context
。 - 调试和统计:
get_chunk_space
、is_empty
和stats
。 - 完整性检查:
check
(可选)。
这种设计使得 PostgreSQL 的内存管理机制既灵活又高效,能够适应多种内存分配策略和应用场景。