本篇文章的內容介紹的是關於PHP7核心剖析9之記憶體管理,現在分享給大家,有需要的朋友可以參考一下
1.Zend記憶體池
記憶體池是核心中最底層的記憶體操作,定義了三種粒度的記憶體區塊:chunk、page、slot,每個chunk的大小為2M,page大小為4KB,一個chunk被切割為512個page,而一個或若干個page被切割為多個slot,所以申請記憶體時依照不同的申請大小決定具體的分配策略:
Huge(chunk): 申请内存大于2M,直接调用系统分配,分配若干个chunk Large(page): 申请内存大于3K(3/4 page_size),小于2044K(511 page_size),分配若干个page Small(slot): 申请内存小于等于3K(3/4 page_size)
## 2.zend堆疊結構
#chunk由512個page組成,其中第一個page用來保存chunk結構,剩下的511個page用於記憶體分配,page主要用於Large、Small兩種記憶體的分配;heap是表示記憶體池的一個結構,它是最主要的一個結構,用於管理上面三種記憶體的分配,Zend中只有一個heap結構。
3.記憶體分配
Huge分配超過2M記憶體的申請,與通用的記憶體申請沒有太大差別,只是將申請的記憶體區塊透過單鍊錶進行了管理。 huge的分配實際上是分配多個chunk,chunk的分配也是large、small記憶體分配的基礎,它是ZendMM向系統申請記憶體的唯一粒度。在申請chunk記憶體時有一個關鍵操作,就是將記憶體位址對齊到ZEND_MM_CHUNK_SIZE,也就是說申請的chunk位址都是ZEND_MM_CHUNK_SIZE的整數倍#Large分配#大於3/4的page_size(4KB)且小於等於511個page_size的記憶體申請,也就是一個chunk的大小夠用(之所以是511個page而不是512個是因為第一個page始終被chunk結構佔用),如果申請多個page的話分配的時候這些page都是連續的。如果直到最後一個chunk也沒找到則重新分配一個新的chunk並插入chunk鍊錶,chunk->free_map利用bitmap來記錄每組的page的使用情況
#
a.首先会直接跳过group1,直接到group2检索 b.在group2中找到第一个可用page位置:67,然后向下找第一个不可用page位置:69,找到的可用内存块长度为2,小于3,表示此内存块不可用 c.接着再次在group2中查找到第一个可用page位置:71,然后向下找到第一个不可用page位置:75,内存块长度为4,大于3,表示找到一个符合的位置,虽然已经找到可用内存块但并不"完美",先将这个并不完美的page_num及len保存到best、best_len,如果后面没有比它更完美的就用它了 d.再次检索,发现group2已无可用page,进入group3,找到可用内存位置:page 130-132,大小比c中找到的合适,所以最终返回的page就是130-132 e.page分配完成后会将free_map对应整数的bit位从page_num至(page_num+page_count)置为1Small分配small記憶體指的是小於(3/4 page_size)的內存,這些記憶體首先也是申請了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
step1: 首先根据申请内存的大小在heap->free_slot中找到对应的slot规格bin_num,如果当前slot为空则首先分配对应的page,free_slot[bin_num]始终指向第一个可用的slot step2: 如果申请内存大小对应的的slot链表不为空则直接返回free_slot[bin_num],然后将free_slot[bin_num]指向下一个空闲位置 step3: 释放内存时先将此内存的next_free_slot指向free_slot[bin_num],然后将free_slot[bin_num]指向释放的内存,也就是将释放的内存插到链表头部相關建議:
以上是PHP7核心剖析9之記憶體管理的詳細內容。更多資訊請關注PHP中文網其他相關文章!