internals:zend_mm
Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
internals:zend_mm [2011/11/09 10:08] laruence [Zend MM] |
internals:zend_mm [2017/09/22 13:28] (current) |
||
---|---|---|---|
Line 3: | Line 3: | ||
* Date: 2011-11-09 | * Date: 2011-11-09 | ||
* Author: Xinchen Hui < | * Author: Xinchen Hui < | ||
- | * Chinese: http:// | + | * Chinese(中文版): http:// |
* First Published at: https:// | * First Published at: https:// | ||
===== Background ===== | ===== Background ===== | ||
< | < | ||
- | <laruence_> Felipe, is there any docs about zend mm? | + | <laruence> Felipe, is there any docs about zend mm? |
- | < | + | < |
</ | </ | ||
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 | + | PHP is written entirely in C. In C, the programmer is responsible for the allocation and release |
- | 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 a common set of requirements. |
- | for small memory, | + | The memory |
- | for large memory, Zend mm is very careful to avoid memory waste. | + | The memory |
+ | 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 MM provides the following (per request) functions: | ||
+ | |||
+ | void* | ||
+ | void* | ||
+ | void* | ||
+ | void | ||
+ | |||
+ | They all share prototype and functionality with the standard C implementation, | ||
+ | |||
+ | 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, | ||
+ | |||
+ | 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 143: | Line 172: | ||
{{: | {{: | ||
+ | as I said above, that there is a number of ZEND_MM_NUMBER_BUCKET large_free_bucket, | ||
+ | |||
+ | that means, each item in the large_free_buckets holds the size which with a corresponding index order value 1. | ||
+ | |||
+ | ie: | ||
+ | the heap-> | ||
===== zend_mm_heap-> | ===== zend_mm_heap-> | ||
Line 193: | Line 228: | ||
#define ZEND_MM_LARGE_BUCKET_INDEX(S) zend_mm_high_bit(S) | #define ZEND_MM_LARGE_BUCKET_INDEX(S) zend_mm_high_bit(S) | ||
</ | </ | ||
- | the zend_mm_high_bits return the highest 1 in the s. ie: 0x01001001 will result a 6. | + | the zend_mm_high_bits return the order of highest 1 in the S(bsr in asm). ie: 0x01001001 will result a 6. |
6.2 is there any valid memory bigger than true_size? if not goto 7. | 6.2 is there any valid memory bigger than true_size? if not goto 7. | ||
Line 210: | Line 245: | ||
</ | </ | ||
as I said, the large_free_buckets is kind of trie tree, assuming a true_size(b01001010), | as I said, the large_free_buckets is kind of trie tree, assuming a true_size(b01001010), | ||
- | 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 267: | Line 302: | ||
let's take the b101010 as a example: | let's take the b101010 as a example: | ||
- | a. first compute the index, | + | a. first compute the index, |
- | b. look at second | + | b. look at highest(based on index: m = true_size << (ZEND_MM_NUM_BUCKETS - index)) |
c. if the bit is 0, but the block doesn' | c. if the bit is 0, but the block doesn' | ||
d. if the bit is 1, but the block doesn' | d. if the bit is 1, but the block doesn' | ||
+ | |||
+ | 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" | 6.3-B looking for the smallest "large memory" | ||
Line 286: | Line 323: | ||
</ | </ | ||
- | looking at the (p = p-> | + | Note the (p = p-> |
7. search in the rest_buckets, | 7. search in the rest_buckets, |
internals/zend_mm.1320833335.txt.gz · Last modified: 2017/09/22 13:28 (external edit)