一、PHP内存相关函数
void *ptr=_emalloc(size); // 申请
_efree(ptr); // 释放,释放的是没有传入大小
二、内存基本概念
chunk(仓库):2m大小的内存,一个chunk看分为512个page
page(面粉):4kb大小的内存
各种规格的内存(面包): 内存预分配,使用mmap分配chunk
- small (30种规格),size <= 3k ,每次申请后通过链表形式存储,是为了回收方便。链表指向下一位置, 指针8字节,故最小分割单位8。
- large ,3k<size<2m-4k,4k整数 先定组再定组内偏移
- huge,size >2m-4k,2m整数
三、内存分配流程图
四、small内存
1.
#define ZEND_MM_BINS_INFO(_, x, y) \
_( 0, 8, 512, 1, x, y) \
_( 1, 16, 256, 1, x, y) \
_( 2, 24, 170, 1, x, y) \
_( 3, 32, 128, 1, x, y) \
_( 4, 40, 102, 1, x, y) \
_( 5, 48, 85, 1, x, y) \
_( 6, 56, 73, 1, x, y) \
_( 7, 64, 64, 1, x, y) \
_( 8, 80, 51, 1, x, y) \
_( 9, 96, 42, 1, x, y) \
_(10, 112, 36, 1, x, y) \
_(11, 128, 32, 1, x, y) \
_(12, 160, 25, 1, x, y) \
_(13, 192, 21, 1, x, y) \
_(14, 224, 18, 1, x, y) \
_(15, 256, 16, 1, x, y) \
_(16, 320, 64, 5, x, y) \
_(17, 384, 32, 3, x, y) \
_(18, 448, 9, 1, x, y) \
_(19, 512, 8, 1, x, y) \
_(20, 640, 32, 5, x, y) \
_(21, 768, 16, 3, x, y) \
_(22, 896, 9, 2, x, y) \
_(23, 1024, 8, 2, x, y) \
_(24, 1280, 16, 5, x, y) \
_(25, 1536, 8, 3, x, y) \
_(26, 1792, 16, 7, x, y) \
_(27, 2048, 8, 4, x, y) \
_(28, 2560, 8, 5, x, y) \
_(29, 3072, 4, 3, x, y)
2.small 类型,一次申请一个chunk,分成512个page,根据实际内存(最小8B最大3kb)大小,取page。
3.small内存计算
static zend_always_inline int zend_mm_small_size_to_bin(size_t size)
{
unsigned int t1, t2;
if (size <= 64) {
/* we need to support size == 0 ... */
return (size - !!size) >> 3;
} else {
t1 = size - 1;
t2 = zend_mm_small_size_to_bit(t1) - 3;
t1 = t1 >> t2;
t2 = t2 - 3;
t2 = t2 << 2;
return (int)(t1 + t2);
}
}
五.内存对齐
内存以2m对齐(低21位全为0),高43位决定首地址,低21位决定偏移量
对于huge一定是2m的整数倍;
对于简单small内存,第1位标志位1标识,0x8 ,0-4bit代表规格(bin_num);
对于large内存,第2位标志位1标识,0x4,0-9bit表示分配的页数,
3k 是1,2位共同标识,0xc,0-4bit表示bin_num,16-25bit表示偏移量
六.笔记地址