海山数据库(He3DB)源码详解:MemoryContextData及MemoryContextMethods结构体解析

3 阅读7分钟

海山数据库(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 提供了多种类型的内存上下文实现(如 AllocSetContextSlabContext 等)。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) */
  • 类型MemoryContextMemoryContextData*
  • 作用:指向当前内存上下文的父上下文。
  • 说明
    • 如果当前上下文是顶层上下文,则 parentNULL
    • 支持嵌套内存上下文的层次结构。
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 中用于实现内存上下文的核心结构体,支持以下功能:

  1. 层次结构:通过 parentfirstchildprevchildnextchild 构建嵌套的内存上下文树。
  2. 内存管理:通过 methods 提供多态的内存分配和释放操作。
  3. 调试支持:通过 nameident 提供调试信息。
  4. 回调机制:通过 reset_cbs 支持重置和删除时的回调函数。

这种设计使得 PostgreSQL 的内存管理机制既灵活又高效,能够适应复杂的内存分配和释放需求。


MemoryContextMethods 结构体的作用

MemoryContextMethods 是 PostgreSQL 中定义的一组函数指针,用于实现内存上下文(MemoryContext)的具体操作。每个内存上下文类型(如 AllocSetContextSlabContext 等)都有自己的实现方式,这些函数指针提供了一种统一的接口,允许通过多态的方式操作不同的内存上下文。

以下是对 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 提供了一种统一的接口来操作不同类型的内存上下文,支持以下功能:

  1. 内存分配和释放allocfree_prealloc
  2. 上下文管理resetdelete_context
  3. 调试和统计get_chunk_spaceis_emptystats
  4. 完整性检查check(可选)。

这种设计使得 PostgreSQL 的内存管理机制既灵活又高效,能够适应多种内存分配策略和应用场景。