PHP7 内存管理

1. 内存的实现

在C语言中,开辟/销毁内存的一对函数。

void *ptr=malloc(size); 
free(ptr);

注意:free掉malloc的时候,是怎么知道销毁多大的内存块呢?在申请内存块的头部,保留64位记录内存块的大小,如下图:

2.PHP使用了内存池

2.1 内存池的介绍

      内存池是内核中最底层的内存操作,定义了三种粒度的内存块:chunk、page、slot,每个chunk的大小为2M,page大小为4KB,一个chunk被切割为512个page,而一个或若干个page被切割为多个slot,所以申请内存时按照不同的申请大小决定具体的分配策略。(chunk:内存仓库)

  • 它分为三层:存储层(storage)、堆层(heap)和接口层(emalloc/efree):
  • 存储层通过 malloc()、mmap() 等函数向系统真正的申请内存,并通过 free() 函数释放所申请的内存。
  • 存储层通常申请的内存块都比较大,这里申请的内存大并不是指storage层结构所需要的内存大,
  • 只是堆层通过调用存储层的分配方法时,其以大块大块的方式申请的内存,存储层的作用是将内存分配的方式对堆层透明化。

2.2 内存池中三种不同规格的内存

Huge(chunk): 申请内存大于2M,直接调用系统分配,分配若干个chunk
Large(page): 申请内存大于3K(3/4 page_size),小于2044K(511 page_size),分配若干个page
Small(slot): 申请内存小于等于3K(3/4 page_size)

 

2.2.1 small内存块

         small内存先是申请了1个或多个page,然后再将这些page按固定大小切割了,所以第一步与上一节Large分配完全相同。small内存总共有30种固定大小的规格:8,16,24,32,40,48,56,64,80,96,112,128 ... 1792,2048,2560,3072 Byte,我们把这称之为slot,这些slot的大小是有规律的:最小的slot大小为8byte,前8个slot依次递增8byte,后面每隔4个递增值乘以2。如下图:

 相同规格的内存使用了链表连接:

为什么最小规格是8字节呢?

因为存放了next指针,提供给使用者的时候会把指针清空。

2.2.2 Huge内存块

       超过2M内存的申请,与通用的内存申请没有太大差别,只是将申请的内存块通过单链表进行了管理。huge的分配实际就是分配多个chunk,chunk的分配也是large、small内存分配的基础,它是ZendMM向系统申请内存的唯一粒度。在申请chunk内存时有一个关键操作,那就是将内存地址对齐到ZEND_MM_CHUNK_SIZE,也就是说申请的chunk地址都是ZEND_MM_CHUNK_SIZE的整数倍。

2.2.3 Large内存块

       大于3/4的page_size(4KB)且小于等于511个page_size的内存申请,也就是一个chunk的大小够用(之所以是511个page而不是512个是因为第一个page始终被chunk结构占用),如果申请多个page的话分配的时候这些page都是连续的 。如果直到最后一个chunk也没找到则重新分配一个新的chunk并插入chunk链表。

  1. 首先会直接跳过group1,直接到group2检索。
  2. 在group2中找到第一个可用page位置:67,然后向下找第一个不可用page位置:69,找到的可用内存块长度为2,小于3,表示此内存块不可用。
  3. 接着再次在group2中查找到第一个可用page位置:71,然后向下找到第一个不可用page位置:75,内存块长度为4,大于3,表示找到一个符合的位置,虽然已经找到可用内存块但并不"完美",先将这个并不完美的page_num及len保存到best、best_len,如果后面没有比它更完美的就用它了。
  4. 再次检索,发现group2已无可用page,进入group3,找到可用内存位置:page 130-132,大小比c中找到的合适,所以最终返回的page就是130-132。
  5. page分配完成后会将free_map对应整数的bit位从page_num至(page_num+page_count)置为1。

2.2.4 内存类型标记

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值