MySQL Mem_root Detailed explanation

Source: Internet
Author: User
Tags prev

This article will explain in detail the use of a very broad mem_root structure in MySQL, while eliminating the debug section of the information, only to analyze the normal situation, the use of mem_root in MySQL to do the memory allocation portion.

Prior to the specific analysis, we cited some of the macros used in the structure's use:

#define Malloc_overhead8 //part of the additional space required to be retained during the allocation # define Alloc_max_block_to_drop4096 //follow-up will continue to analyze the purpose of the macro # define Alloc_max_block_usage_before_dropTen //subsequent analysis will continue to analyze the purpose of the macro # define Align_size (a) my_align ((a), sizeof (Double)) #define MY_ALIGN (a,l) ((A)+L- 1)& ~((L)- 1)) #define ALLOC_ROOT_MIN_BLOCK_SIZE (Malloc_overhead+sizeof (USED_MEM)+ 8)/*Define Some useful general macros (should is done after all headers).*//*www.manongjc.com*/#define MY_MAX (A, B) (a)>(b)? (a): (b))//find the maximum value between two values # # my_min (A, B) ((a)<(b)? (a): (b))//Find the minimum value between two values

Let's look at the information about the MEM_ROOT structure:

typedef struct st_mem_root{Used_mem*Free/*Free block Link List's list header pointer*/Used_mem*Used;/*used block link list's linked list head pointer*/Used_mem*Pre_alloc;/*Pre-allocated block*/size_t Min_malloc; /*if the remaining free space on the block is less than this value, it will be moved from the Used list to the*/size_t block_size; /*The amount of space per initialization*/unsignedintBlock_num;/*record the actual number of blocks, initialized to 4*/unsignedintFirst_block_usage;/*the first block test in the free list does not meet the number of allocated space sizes*/Void (*Error_Handler) (void);/*error handling function for allocation failure*/} mem_root;

The following is the allocation of specific block information.

typedef struct st_used_mem{     *next// point to next allocated block    int  left// The block's remaining space size     int// Total size of the block} Used_mem ;

In fact mem_root in the allocation process, is through the two-way list to manage the used and free block:

The initialization process for Mem_root is as follows:

void Init_alloc_root (Mem_root*Mem_root, size_t block_size, size_t pre_alloc_size __attribute__ ((unused))) {Mem_root -Free=Mem_root -Used=Mem_root -Pre_alloc= 0; Mem_root -Min_malloc=  +; 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;}

During initialization, the block_size space is block_size-alloc_root_min_block_size. Because in memory is not enough, need to expand, is through Mem_root->block_num >>2 * block_size to expand, so Mem_root->block_num >>2 is at least 1, So in the process of initialization mem_root->block_num=4 (note: 4>>2=1).

Here's a look at the steps to allocate memory specifically:

void*Alloc_root (mem_root*mem_root, size_t length)    {size_t get_size, block_size; Uchar*Point ; REG1 Used_mem*Next = 0; REG2 Used_mem**prev; Length=align_size (length); if( (*(prev= &Mem_root -Free))!= NULL )    {        if( (*Prev->left <Length&&Mem_root -First_block_usage++ >=Alloc_max_block_usage_before_drop&&             (*Prev->left <Alloc_max_block_to_drop) {            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 = *PrevNext && Next->left <LengthNext = 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=Length+align_size (sizeof (USED_MEM)); Get_size=My_max (get_size, block_size); if( ! (Next =(Used_mem*) My_malloc (Get_size, MYF (my_wme|me_fatalerror)) ) )        {            if(Mem_root -Error_Handler) (*Mem_root -Error_Handler)            (); Dbug_return (void*)0);/*purecov:inspected*/} mem_root -Block_num++; Next -Next    = *prev; Next -Size=get_size; Next->left    =Get_size-Align_size (sizeof (USED_MEM));/*BUG: If the block was calculated by Mem_root->block_size * (Mem_root->block_num >> 2), the Align_size (sizeof ( USED_MEM), repeated here. */        *Prev= Next; } Point=(Uchar*) ( (Char *)Next +(Next -Size- Next->left) );/*Todo:next part is unneded due to mem_root->first_block_usage counter*//*www.manongjc.com*/    if( (Next->left -=Length<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; }}

The specific logic of the above code is as follows:

1. Look for the free link list to find the block that satisfies the space. If a suitable block is found, then:
1.1 Return the block directly from the initial address at Size-left. Of course, during the free list traversal, the free list is judged
The left space in the first block does not meet the space that needs to be allocated, and the block has been looked up 10 times
(Alloc_max_block_usage_before_drop) does not satisfy the allocation length, and the BLOCK's remaining space is less than
4 K (Alloc_max_block_to_drop), the BLOCK is moved to the used linked list.

2. If the free list does not have a suitable block, then:
2.1 Assigned Mem_root->block_size * (Mem_root->block_num >> 2) and length+align_size (sizeof (USED_MEM))
Medium ratio is larger as the new block memory space.
2.2 Based on the use of the block, the block is hung on the used or free linked list.

It is important to note the use of level two pointers:

 for (Next= *prevNext Next next) prev= &next;}

Prev points to the address of the last block's next point:

So replace the address of the prev with the address of the new block, and the new block is added to the end of the free list: *prev=next;

Summarize:

Mem_root's memory allocation is based on the heuristic allocation algorithm, and as the number of subsequent blocks increases, the memory of a single block becomes larger: block_size= mem_root->block_size * (mem_root->block_ Num >> 2).

MySQL Mem_root Detailed explanation

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.