mysql my malloc_mysql层的内存分配

本文介绍MySQL内存池的工作原理,包括初始化、内存分配与释放过程。内存池能够有效地管理内存,减少内存碎片,提高应用程序的效率。

mysql内存池

mysql内部使用的内存管理程序,可以实现多次申请内存块, 中途任何时刻失败, 或者下次使用前释放内存, 无需再关心每次申请和释放了哪些内存.

工作原理:

初始化定义每次分配的最小内存块大小M,如果申请一次内存, 大小为X, X大于M, 就分配一块X的内存, 加入到管理链表中.如果小于的话, 看之前剩余的还够不够, 如果足够的话, 返回之前多余的内存地址.如果不够,则申请这么大的内存, 也计入链表中。

释放是一次性的,也可以不释放内存,而是标记已经使用的内存为“未使用”,下次同样的应用可以继续使用。

创建内存池/*Initialize memory root

SYNOPSIS

init_alloc_root()

mem_root - memory root to initialize

block_size - size of chunks (blocks) used for memory allocation

(It is external size of chunk i.e. it should include

memory required for internal structures, thus it

should be no less than ALLOC_ROOT_MIN_BLOCK_SIZE)

pre_alloc_size - if non-0, then size of block that should be

pre-allocated during memory root initialization.

DESCRIPTION

This function prepares memory root for further use, sets initial size of

chunk for memory allocation and pre-allocates first block if specified.

Altough error can happen during execution of this function if

pre_alloc_size is non-0 it won't be reported. Instead it will be

reported as error in first alloc_root() on this memory root.*/

void init_alloc_root(MEM_ROOT *mem_root, uintblock_size,uintpre_alloc_size __attribute__((unused))) {

DBUG_ENTER("init_alloc_root");

mem_root->free = mem_root->used = mem_root->pre_alloc = 0;

mem_root->min_malloc = 32;

mem_root->block_size = block_size -ALLOC_ROOT_MIN_BLOCK_SIZE;

mem_root->error_handler = 0;

mem_root->block_num = 4; /*We shift this with >>2*/mem_root->first_block_usage = 0;if(pre_alloc_size) {if ((mem_root->free = mem_root->pre_alloc = (USED_MEM*) my_malloc(

pre_alloc_size+ ALIGN_SIZE(sizeof(USED_MEM)),

MYF(0))))

{

mem_root->free->size= pre_alloc_size+ALIGN_SIZE(sizeof(USED_MEM));

mem_root->free->left=pre_alloc_size;

mem_root->free->next= 0;

}

}

DBUG_VOID_RETURN;

}

申请内存

gptr alloc_root(MEM_ROOT*mem_root, unsigned intSize) {uintget_size, block_size;

gptr point;

reg1 USED_MEM*next = 0;

reg2 USED_MEM**prev;

DBUG_ENTER("alloc_root");DBUG_ASSERT(alloc_root_inited(mem_root));

Size=ALIGN_SIZE(Size);if ((*(prev = &mem_root->free)) !=NULL)

{if ((*prev)->left first_block_usage++

>=ALLOC_MAX_BLOCK_USAGE_BEFORE_DROP&& (*prev)->left

{

next= *prev;*prev = next->next; /*Remove block from list*/next->next = mem_root->used;

mem_root->used =next;

mem_root->first_block_usage = 0;

}for (next = *prev; next && next->left < Size; next = next->next)

prev= &next->next;

}if (!next) { /*Time to alloc new block*/block_size= mem_root->block_size * (mem_root->block_num >> 2);

get_size= Size + ALIGN_SIZE(sizeof(USED_MEM));

get_size=max(get_size, block_size);if (!(next = (USED_MEM*) my_malloc(get_size, MYF(MY_WME)))) {if (mem_root->error_handler)

(*mem_root->error_handler)();return ((gptr) 0); /*purecov: inspected*/}

mem_root->block_num++;

next->next = *prev;

next->size =get_size;

next->left = get_size - ALIGN_SIZE(sizeof(USED_MEM));*prev =next;

}

point= (gptr) ((char*) next + (next->size - next->left));/*TODO: next part may be unneded due to mem_root->first_block_usage counter*/

if ((next->left -= Size) < mem_root->min_malloc) { /*Full block*/

*prev = next->next; /*Remove block from list*/next->next = mem_root->used;

mem_root->used =next;

mem_root->first_block_usage = 0;

}DBUG_RETURN(point);

}

释放内存/*Deallocate everything used by alloc_root or just move

used blocks to free list if called with MY_USED_TO_FREE

SYNOPSIS

free_root()

root Memory root

MyFlags Flags for what should be freed:

MY_MARK_BLOCKS_FREED Don't free blocks, just mark them free

MY_KEEP_PREALLOC If this is not set, then free also the

preallocated block

NOTES

One can call this function either with root block initialised with

init_alloc_root() or with a bzero()-ed block.

It's also safe to call this multiple times with the same mem_root.*/

void free_root(MEM_ROOT *root, myf MyFlags) {

reg1 USED_MEM*next, *old;

DBUG_ENTER("free_root");if (!root) /*QQ: Should be deleted*/DBUG_VOID_RETURN;/*purecov: inspected*/

if (MyFlags &MY_MARK_BLOCKS_FREE)

{

mark_blocks_free(root);

DBUG_VOID_RETURN;

}if (!(MyFlags &MY_KEEP_PREALLOC))

root->pre_alloc = 0;for (next = root->used; next;) {

old=next;

next= next->next;if (old != root->pre_alloc)

my_free((gptr) old, MYF(0));

}for (next = root->free; next;) {

old=next;

next= next->next;if (old != root->pre_alloc)

my_free((gptr) old, MYF(0));

}

root->used = root->free = 0;if (root->pre_alloc) {

root->free = root->pre_alloc;

root->free->left = root->pre_alloc->size - ALIGN_SIZE(sizeof(USED_MEM));

TRASH_MEM(root->pre_alloc);

root->free->next = 0;

}

root->block_num = 4;

root->first_block_usage = 0;

DBUG_VOID_RETURN;

}

内存池使用实例voidtest_myalloc() {

MEM_ROOT root;char *str;

init_alloc_root(&root, 1 << 12, 1 << 10);

str= (char *) alloc_root(&root, 1024 * sizeof(double));if (NULL ==str)

printf("cannot get memory for alloc root for str\n");

strcpy(str,"hello\n");

puts(str);//mark free, can be used again

free_root(&root, MY_MARK_BLOCKS_FREE);//free, can not be used

free_root(&root, 0);

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值