5.如何使用内存上下文
使用内存上下文之前,我们需要先对其进行创建。AntDB启动时已经创建并初始化好了部分内存上下文,例如:TopMemoryContext。这个TopMemoryContext是所有内存上下文的父节点或者祖先节点。一般我们创建的内存上下文都在TopMemoryContext的子层以下。创建完之后,我们便可以通过palloc/palloc0使用该内存上下文,且使用完成之后可以释放内存上下文。
5.1 创建内存上下文
我们通过AllocSetContextCreate来创建内存上下文,这是一个宏定义。实际处理是由AllocSetContextCreateInternal来完成的。
图8:AllocSetContextCreateInternal函数定义
・parent:我们需要指定父节点的内存上下文。根据程序适当的设定。
・name:内存上下文的名称。
・minContextSize:内存上下文的最小尺寸。
・initBlockSize:内存上下文的初始尺寸。
・maxBlockSize:内存上下文的最大尺寸。
最后会调用MemoryContextCreate函数创建内存上下文。
5.2 在内存上下文中使用内存
在申请内存之前我们需要考虑:当前内存应该在哪一个内存上下文申请。不同的内存上下文,使用目的、生命周期都是不一样的。决定好内存上下文之后,我们可调用MemoryContextSwitchTo函数切换至目标内存上下文。
MemoryContextSwitchTo函数的作用是切换至目标上下文,并返回当前的内存上下文。一般使用方法请参照:
1) 当前内存上下文 = MemoryContextSwitchTo(目标内存上下文)。
2) 进行内存申请等操作。这时候申请的内存都是在目标上下文中。
3) 根据自己的代码处理逻辑。如果有需要,请及时切换回当前内存上下文。MemoryContextSwitchTo(当前内存上下文)。
内存上下文的切换不当,或者切换不及时的话,都可能会带来预料之外的后果,甚至直接导致程序崩溃。举个很简单的例子说明一下,如图9所示。
图9:内存上下文切换不当示例
一旦决定好所需要用的内存上下文之后,我们就可以调用内存分配函数palloc/palloc0来申请内存了。注意一点,palloc0会在申请完内存之后把内存全部初始化成0,而palloc申请的内存的内容是不确定的。这两个函数的最终都是由AllocSetAlloc来实现。
内存使用完之后,可以调用pfree来释放。这个函数指向的是AllocSetFree函数。在AntDB中,palloc的内存也并不是一定要调用pfree来释放内存。内存的释放工作可以留到内存上下文的释放阶段执行。
当然还有其他内存相关的各种操作,realloc、reset等等。它们指向的函数在前面的4.2.1章节都已列出来了。
5.3 释放内存上下文
我们可以调用MemoryContextDelete来删除不再使用的内存上下文。如果仅仅是想释放内存上下文中的某些内存片的话,可以调用pfree来释放部分内存。注意一点,这个pfree操作只是把内存还给内存上下文,并不是还给操作系统。AntDB还提供了一个内存重置reset的功能,这个reset可以释放所有内存块(除了特别设置成保留的内存块,保留内存块内容会被清除)。
6.总结
本篇文章给大家简单地介绍了内存上下文的基本概念,希望大家阅读之后对内存上下文有些基本的了解,以后再看到类似的代码不会过于陌生。同时,对本文一开始提出的几点疑惑,大家心中应该也找到了答案。
当然,本文只介绍了内存上下文的部分内容,还有很多的知识没有在文中进行阐述,比如:结构体中其他的成员变量干什么的;创建内存上下文是个什么流程;申请内存是个什么流程,有什么算法等等。还有,内存上下文有什么坑;有什么参数能控制内存上下文大小吗;AntDB对内存上下文的持续改进……我们会在接下来的文章里继续和大家慢慢分享。先有概念,再有细节。本文就是建立概念的过程,来为后面讲解细节奠定基础。
最后,给各位数据库爱好者、技术爱好者一点建议。技术不是通过阅读一些技术文章就能提升的,我们需要自己动手实验、调试,才能把看到的内容转化成自己的知识。欢迎大家关注我们AntDB,跟我们一起在数据库的世界里共同探索,一起成长。