MEM_ROOT for MySQL

Source: Internet
Author: User

MEM_ROOT for MySQL
This article will describe in detail the widely used MEM_ROOT struct in MySQL, while saving the debugging information. It will only analyze the memory allocation in mysql under normal conditions.

Before the specific analysis, we set a precedent for some macros used in the use of this struct:

 
 
  1. # Define MALLOC_OVERHEAD 8 // some additional space needs to be retained during the allocation process
  2. # Define ALLOC_MAX_BLOCK_TO_DROP 4096 // the usage of the macro will be analyzed later
  3. # Define ALLOC_MAX_BLOCK_USAGE_BEFORE_DROP 10 // The Macro will be analyzed later

  4. # Define ALIGN_SIZE (A) MY_ALIGN (A), sizeof (double ))
  5. # Define MY_ALIGN (A, L) (A) + (L)-1 )&~ (L)-1 ))

  6. # Define ALLOC_ROOT_MIN_BLOCK_SIZE (MALLOC_OVERHEAD + sizeof (USED_MEM) + 8)
  7. /* Define some useful general macros (shocould be done after all headers ).*/
  8. # Define MY_MAX (a, B) (a)> (B )? (A): (B) // calculate the maximum value between two values.
  9. # Define MY_MIN (a, B) (a) <(B )? (A): (B) // calculates the minimum value between two values.

Next let's take a look at the MEM_ROOT struct information:
 
 
  1. Typedef struct st_mem_root
  2. {
  3. USED_MEM * free; // The linked list header pointer of the free block link list.
  4. USED_MEM * used; // chain table head pointer of used block link list
  5. USED_MEM * pre_alloc; // pre-allocated block
  6. Size_t min_malloc; // if the remaining available space of the block is smaller than this value, it will be moved from free list to used list
  7. Size_t block_size; // size of the Space initialized each time
  8. Unsigned int block_num; // record the actual number of blocks, initialized to 4
  9. Unsigned int first_block_usage; // number of times the first block test in the free list does not meet the size of the allocated space
  10. Void (* error_handler) (void); // error handling function for allocation failure
  11. } MEM_ROOT;

The following describes how to allocate specific block information.
 
 
  1. Typedef struct st_used_mem
  2. {
  3. Struct st_used_mem * next; // point to the next allocated block
  4. Unsigned int left; // The remaining space of the block
  5. Unsigned int size; // The total size of the block
  6. } USED_MEM;
In fact, MEM_ROOT manages used and free blocks through a two-way linked list during the allocation process:


The initialization process of MEM_ROOT is as follows:
 
 
  1. void init_alloc_root(MEM_ROOT *mem_root, size_t block_size,size_t pre_alloc_size __attribute__((unused)))
  2. {
  3. mem_root->free= mem_root->used= mem_root->pre_alloc= 0;
  4. mem_root->min_malloc= 32;
  5. mem_root->block_size= block_size - ALLOC_ROOT_MIN_BLOCK_SIZE;
  6. mem_root->error_handler= 0;
  7. mem_root->block_num= 4; /* We shift this with >>2 */
  8. mem_root->first_block_usage= 0;
  9. }

Block_size space is a block_size-ALLOC_ROOT_MIN_BLOCK_SIZE during initialization. Because the memory is not enough and you need to resize it through mem_root-> block_num> 2 * block_size, mem_root-> block_num> 2 must be at least 1, therefore, during the initialization process, mem_root-> block_num = 4 (Note: 4> 2 = 1 ).

Next let's take a look at the specific steps to allocate memory:
 
 
  1. Void * alloc_root (MEM_ROOT * mem_root, size_t length)
  2. {
  3. Size_t get_size, block_size;
  4. Uchar * point;
  5. Reg1 USED_MEM * next = 0;
  6. Reg2 USED_MEM ** prev;

  7. Length = ALIGN_SIZE (length );
  8. If (* (prev = & mem_root-> free ))! = NULL)
  9. {
  10. If (* prev)-> left <length &&
  11. Mem_root-> first_block_usage ++> = ALLOC_MAX_BLOCK_USAGE_BEFORE_DROP &&
  12. (* Prev)-> left <ALLOC_MAX_BLOCK_TO_DROP)
  13. {
  14. Next = * prev;
  15. * Prev = next-> next;/* Remove block from list */
  16. Next-> next = mem_root-> used;
  17. Mem_root-> used = next;
  18. Mem_root-> first_block_usage = 0;
  19. }
  20. For (next = * prev; next & next-> left <length; next = next-> next)
  21. Prev = & next-> next;
  22. }
  23. If (! Next)
  24. {/* Time to alloc new block */
  25. Block_size = mem_root-> block_size * (mem_root-> block_num> 2 );
  26. Get_size = length + ALIGN_SIZE (sizeof (USED_MEM ));
  27. Get_size = MY_MAX (get_size, block_size );

  28. If (! (Next = (USED_MEM *) my_malloc (get_size, MYF (MY_WME | ME_FATALERROR ))))
  29. {
  30. If (mem_root-> error_handler)
  31. (* Mem_root-> error_handler )();
  32. DBUG_RETURN (void *) 0);/* purecov: inspected */
  33. }
  34. Mem_root-> block_num ++;
  35. Next-> next = * prev;
  36. Next-> size = get_size;
  37. Next-> left = get_size-ALIGN_SIZE (sizeof (USED_MEM); // bug: If the block is calculated through mem_root-> block_size * (mem_root-> block_num> 2, ALIGN_SIZE (sizeof (USED_MEM) has been removed, which is repeated here.
  38. * Prev = next;
  39. }

  40. Point = (uchar *) (char *) next + (next-> size-next-> left ));
  41. /* TODO: next part may be unneded due to mem_root-> first_block_usage counter */
  42. If (next-> left-= length) <mem_root-> min_malloc)
  43. {/* Full block */
  44. * Prev = next-> next;/* Remove block from list */
  45. Next-> next = mem_root-> used;
  46. Mem_root-> used = next;
  47. Mem_root-> first_block_usage = 0;
  48. }
  49. }

The specific logic of the above Code is as follows: 1. view the free linked list to find a block that satisfies the space. If a proper block is found, 1.1 returns the initial address of the block from size-left. Of course, in the free list traversal process, the left space in the first block in freelist is determined not to meet the space to be allocated, this block has been searched for 10 times (ALLOC_MAX_BLOCK_USAGE_BEFORE_DROP) and does not meet the allocation length. If the remaining space of this block is less than 4 k (ALLOC_MAX_BLOCK_TO_DROP), the block is moved to the used linked list. 2. if no suitable block exists in the free linked list, mem_root-> block_size * (mem_root-> block_num> 2) and length + ALIGN_SIZE (sizeof (USED_MEM) are allocated to 2.1 )) as the new block memory space. 2.2 According to the usage of the block, the block is mounted on the used or free linked list.
Note the usage of level 2 pointers:
 
 
  1. for (next= *prev ; next && next->left < length ; next= next->next)
  2. prev= &next->next;
  3. }
Prev points to the address pointed to by the next of the last block:

Therefore, replace the prev address with the newblock address, and add the new block to the end of the free list: * prev = next;


Conclusion: MEM_ROOT uses a heuristic Allocation Algorithm for memory allocation. As the number of blocks increases, the memory size of a single block increases: block_size = mem_root-> block_size * (mem_root-> block_num> 2 ).

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.