目录
1 为什么使用mysql内存池
2 mysql内存池的基本用法
3 mysql内存池如何工作的
4 两个最常用的使用场景
5 mysql内存池的代码说明
6一个简单的例子
1 为什么使用mysql内存池
可以简化程序内存的管理. Mysql内部使用的就是它. 可以实现多次申请内存块, 中途任何时刻失败, 或者下次使用前释放内存, 无需再关心每次申请和释放了哪些内存.
2 mysql内存池的基本用法
主要使用这3个函数(其他函数请查看my_alloc.h):
2.1 初始化内存池:
void init_alloc_root(MEM_ROOT *mem_root, size_t block_size, size_t pre_alloc_size __attribute__((unused)));
block_size 申请的内存块最小内存
使用实例:
MEM_ROOT JsonMemRoot;
init_alloc_root(&JsonMemRoot, 1<<12, 0);
2.2 在内存池中申请使用一块内存
void * alloc_root(MEM_ROOT *mem_root, size_t length);
length 申请的内存块内存, 如果前面申请的没有用完, 将使用前面的.
如果已经用完了将申请新的, 如果新申请的不能被sizeof(double) 整除, 则增大它使之整除(内存对齐).
取length和init_alloc_root中的block_size, 其中的较大值申请新的内存
使用实例:
static int TestMemRoot()
{
char * str = (char *) alloc_root(&JsonMemRoot, 1024 * sizeof(char));
if (NULL == str)
{
WriteLogNF("TestMemRoot : cannot alloc_root for str\\n");
return -1;
}
return 0;
}
2.3 释放内存池
(MyFlags : MY_MARK_BLOCKS_FREE : 将以前申请的内存设为可用, 内存池的内存下次还能使用;
MY_KEEP_PREALLOC: 保持以前新建的内存块
0 释放内存)
void free_root(MEM_ROOT *root, int flags);
使用实例:
free_root(&JsonMemRoot, 0); // 释放内存池内存
free_root(&JsonMemRoot, MY_MARK_BLOCKS_FREE); // 标记已经使用的内存为释放, 下次可以继续使用, 不能使用宏MY_MARK_BLOCKS_FREE, 可以填入2
3 mysql内存池如何工作的
初始化定义每次分配的最小内存块大小M
如果申请一次内存, 大小为X, X大于M, 就分配一块X的内存, 加入到管理链表中.
如果小于的话, 看之前剩余的还够不够, 如果足够的话, 返回之前多余的内存地址.
如果不够, 则申请这么大的内存, 也计入链表中
释放是一次性的. 也可以不释放内存. 而是标记已经使用的内存为"未使用". 下次同样的应用可以继续使用
4 两个最常用的使用场景
一个很大的结构体, 很多操作步骤, 或者一个有很多连续步骤的函数. 大部分步骤都需要申请和释放内存.
4.1 每个结构体或函数需要维护不同的内存
如果是结构体, 则在结构体添加一个MEM_ROOT, 初始化结构体时也初始化MEM_ROOT; 如果是函数, 则在函数开始定义和初始化一个MEM_ROOT的局部变量. 中途任何位置出错或者完成 只需释放该MEM_ROOT即可.
4.2 每个结构体或函数每次执行后的结果与中间申请的内存无关
只需定义一个全局static MEM_ROOT变量, 程序启动时初始化MEM_ROOT; 程序退出时释放内存; 到了新的任务, 标记原来的内存为释放, 然后继续使用; 中途失败无需释放.
5 mysql内存池的代码说明
my_alloc.c 文件取自 mysql源码目录下的 mysys/my_alloc.c, 经过修改的得到
my_alloc.h 文件取自 mysql源码目录下的 include/my_alloc.h, 经过修改的得到
如果使用mysql环境, 可以不用加入这两个文件到工程, 而是按下面的方式引用文件, 之后直接使用上面的函数:
#include
#include
#include
#include
6 一个简单的例子
static void Test
{
MEM_ROOT JsonMemRoot;
char * str;
init_alloc_root(&JsonMemRoot, 1<<12, 0);
str = (char *) alloc_root(&JsonMemRoot, 1024 * sizeof(char));
if (NULL == str)
{
WriteLogNF("TestMemRoot : cannot alloc_root for str\\n");
return -1;
}
strcpy(str, "hello\\n");
puts(str);
free_root(&JsonMemRoot, MY_MARK_BLOCKS_FREE);
puts(str);
free_root(&JsonMemRoot, 0);
}