internals:zend_mm

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
Next revision Both sides next revision
internals:zend_mm [2011/11/09 12:39]
laruence
internals:zend_mm [2013/01/22 13:26]
krakjoe [Zend MM]
Line 3: Line 3:
   * Date: 2011-11-09   * Date: 2011-11-09
   * Author: Xinchen Hui <laruence@php.net>   * Author: Xinchen Hui <laruence@php.net>
-  * Chinese: http://www.laruence.com/2011/11/09/2277.html+  * Chinese(中文版): http://www.laruence.com/2011/11/09/2277.html
   * First Published at: https://wiki.php.net/internals/zend_mm   * First Published at: https://wiki.php.net/internals/zend_mm
  
 ===== Background ===== ===== Background =====
 <code> <code>
-<laruence_> Felipe, is there any docs about zend mm?   +<laruence> Felipe, is there any docs about zend mm?   
-<Felipe> laruence_: almost nothing... just Zend/README.ZEND_MM +<Felipe> laruence: almost nothing... just Zend/README.ZEND_MM 
 </code> </code>
 So I decided to write one, to describe the whole implement of Zend mm(memory allocating, memory freeing) So I decided to write one, to describe the whole implement of Zend mm(memory allocating, memory freeing)
Line 15: Line 15:
 I am not good at english, so if you find some wrong words, plz feel free to edit it. I am not good at english, so if you find some wrong words, plz feel free to edit it.
 ===== Zend MM ===== ===== Zend MM =====
-Zend mm is the memory manager of PHP,  it apply memory from OS, then allocate the memory to PHP script by emalloc.+PHP is written entirely in C. In C, the programmer is responsible for the allocation and release of memory during runtime
  
-Zend mm divides memory into two type, small memory and large memory+PHP has very specific requirements for management of memory and many modes of execution; all sharing the same set of requirements
  
-for small memory,  Zend mm target at emalloc/efree quickly and also has a cache mechanism for them.+The memory manager in PHPnamed Zend MMfacilitates these requirements in the same way, whatever the mode of execution, whatever the code.
  
-for large memory,  Zend mm is very careful to avoid memory waste. +The memory manager has two distinct types of allocation:
  
 + small: when allocating small blocks of memory, it is important that the manager is fast and efficient. 
 +
 + large: when allocating large blocks of memory, it is important that the manager minimizes wastage.
 +
 +The developer makes allocations that have two distinct life cycles:
 +
 + request: the most common type of allocation made; the developer requires the memory to service the current request
 +
 + persistent: the developer intends to reference the memory in multiple requests
 +
 +The MM provides the following (per request) functions:
 +
 + void*  emalloc(size_t size);
 + void*  erealloc(void* pointer, size_t size);
 + void*  ecalloc(size_t num, size_t count);
 + void   efree(void* pointer);
 +
 +They all share prototype and functionality with the standard C implementation, but the memory returned is optimized, and tracked. Tracking memory allows a margin of error not normally present in C programming: memory that is not free'd explicitly will normally be free'd by the implementation at the appropriate time, such as the end of the request, or the end of execution.
 +
 +Zend provides the following (persistence) functions:
 +
 + void* pemalloc(size_t size, zend_bool persistent);
 + void* perealloc(void* pointer, size_t size, zend_bool persistent);
 + void* pecalloc(size_t num, size_t count, zend_bool persistent);
 + void  pefree(void* pointer, zend_bool persistent);
 +
 +Persistent memory is not optimized, or tracked by the implementation, and should only be used if the developer requires a structure to survive requests.
 +
 +The following diagrams and explanations provide insight into how and why Zend MM manages the per request memory it allocates.
 ===== Struct zend_mm_heap ===== ===== Struct zend_mm_heap =====
 <code c> <code c>
Line 216: Line 245:
 </code> </code>
 as I said, the large_free_buckets is kind of trie tree, assuming a true_size(b01001010), Zend vm try to find the best_fit by hash the binary value as a 'key'. as I said, the large_free_buckets is kind of trie tree, assuming a true_size(b01001010), Zend vm try to find the best_fit by hash the binary value as a 'key'.
-that is,  Zend MM start from large_free_buckets[index], try to find the best fit size memory for the true size accroding to the each bit of the true_size.+that is,  Zend MM start from large_free_buckets[4], try to find the best fit size memory for the true size accroding to the each bit of the true_size.
 <code c> <code c>
     if (UNEXPECTED((bitmap & 1) != 0)) {     if (UNEXPECTED((bitmap & 1) != 0)) {
Line 273: Line 302:
 let's take the b101010 as a example: let's take the b101010 as a example:
  
-a. first compute the index,  if the memory at the index is exactly  is the same size as true_size, then allocating succeed, and return the block->next_free_buckets.+a. first compute the index,  if the memory block in the large_free_buckets[indexis exactly  is the same size as true_size, then allocating succeed, and return the block->next_free_buckets.
  
-b. look at second bit of the true_size, it's 0, so Zend MM will looking for the best fit in the block->child[0], if the block->child[0] is the same size as true_size, then allocating succeed, return, if it's 1, Zend MM will do the looking loop in the block->child[1].+b. look at highest(based on index: m = true_size << (ZEND_MM_NUM_BUCKETS - index)) bit of the true_size, it's 0, so Zend MM will looking for the best fit in the block->child[0], if the block->child[0] is the same size as true_size, then allocating succeed, return, if it's 1, Zend MM will do the looking loop in the block->child[1].
  
 c. if the bit is 0, but the block doesn't has a child[0]? Zend MM will try to find the samllest memory under the block->child[1]. c. if the bit is 0, but the block doesn't has a child[0]? Zend MM will try to find the samllest memory under the block->child[1].
  
 d. if the bit is 1, but the block doesn't has a child[1], goto 6.3-B d. if the bit is 1, but the block doesn't has a child[1], goto 6.3-B
 +
 +f. left shift m(which make the next bit in the true_size will be considered in the next loop), and make the current node as child[1] or child[0](described above), then goto a, start a new loop.
  
 6.3-B looking for the smallest "large memory". if found, allocating succeed, and return best_fit->next_free_block. 6.3-B looking for the smallest "large memory". if found, allocating succeed, and return best_fit->next_free_block.
Line 292: Line 323:
 </code> </code>
  
-looking at the (p = p->child[p->child[0] != NULL]), Zend MM is trying to find the "smallest" one.+Note the (p = p->child[p->child[0] != NULL]), Zend MM is trying to find the "smallest" one.
  
 7. search in the rest_buckets, it is a list. used to cache some big size memory before put them into free_buckets, if found allocating succeed, and return 7. search in the rest_buckets, it is a list. used to cache some big size memory before put them into free_buckets, if found allocating succeed, and return
internals/zend_mm.txt · Last modified: 2017/09/22 13:28 (external edit)