PHP原始碼分析(記憶體管理)

2021-09-22 16:25:23 字數 2090 閱讀 8830

void *ptr=_emalloc(size);

_efree(*ptr)   //釋放記憶體的時候只傳入ptr,並沒有傳入釋放記憶體大小

當我們申請乙個size大小的記憶體的時候,我們多申請一些存起來,下次使用者申請的時候,直接給出相應大小的記憶體即可,這樣減少了使用者態和核心態的切換,提高效率,記憶體**的時候需要知道這個記憶體屬於哪個記憶體頁page,屬於哪個chunk,以便**

chunk記憶體會進行記憶體的預分配,使用mmap分配chunk

記憶體分類: small(30種規格)(size<=3kb)

large(3kbhuge(size>2mb-4kb)  //如果申請3mb記憶體,肯定返回比3mb大且2mb倍數記憶體

比如申請大小為7的記憶體,返回的大小為8的記憶體

記憶體分配流程:

如果有現成已經滿足需要的small記憶體就直接返回,否則執行small_slow函式

呼叫mmap會申請大的記憶體

當呼叫samll_slow會先去large記憶體裡面取乙個page,如果page用完了,會從mm_chunk_alloc裡面申請乙個chunk

在small的30個規格中:

比如申請乙個size是7的,我是直接找到包含7的最小的size,比如申請乙個size=8的話,直接申請乙個page,切割成了512個,其中乙份返回回去,剩下的511個掛在

申請small記憶體的時候:1、要找到size最小的規格   2、然後在chunk上申請乙個page,如果乙個page不夠用的話,申請3個page,分成四份,把其中乙份返回給使用者,剩下的儲存在mm_heap

回顧下free_slot欄位的定義:

zend_mm_free_slot *free_slot[zend_mm_bins];

struct zend_mm_free_slot

mm_heap裡面有乙個free_slot,是乙個陣列,掛了0-29,比如我們申請512的8位元組,把第乙個返回,剩下的511個按照鍊錶的方式存起來

思考:為什麼最小是8位元組記憶體塊

可以看出空閒記憶體鍊錶的每個節點都是乙個zend_mm_free_slot結構體,其只有乙個next指標字段;因為8個位元組恰好放next指標,因為需要維護鍊錶,這裡有乙個next指標,需要占用記憶體的

思考:對於8位元組大小的記憶體塊,其next指標就需要佔8位元組的空間,那使用者的資料儲存在**呢?

答案:free_slot是small記憶體的空閒鍊錶,空閒指的是未分配記憶體,此時是不需要儲存其他資料的;當分配給使用者時,此節點會從空閒鍊錶刪除,也就不需要維護next指標了;使用者可以在8位元組裡儲存任何資料;

思考:如何快速找到包含所需記憶體大小的最小規格呢?

答案:

chunk的記憶體對齊

1、怎麼定位快要釋放記憶體是多大的

對任意位址p,如何計算頁號? --2m位元組對齊

chunk的大小為2m,首位址高43位為數字,低21位為0,他的位址為2m的整數倍

如何確保乙個chunk的位址時2m位元組對齊的呢?

我們申請記憶體的時候是由記憶體頁來管理的,我們malloc出來的記憶體位址一定是4k的整數倍,

Redis原始碼分析 記憶體管理

原始碼版本 redis 2.4.4 redis記憶體相關函式都放在zmalloc.h zmalloc.c中 redis中可以使用tcmalloc jemalloc makefile ifeq use tcmalloc yes alloc dep alloc link ltcmalloc alloc ...

FreeRTOS記憶體管理原始碼分析

記憶體管理一直都是重中之重的知識。記憶體管理在freertos系統中是可裁剪可配置的。freertos提供了5種記憶體管理方案。暫時可能分析不完5種方案,今天能寫多少先寫多少,後續有時間了再一點一點的寫吧。5中方案對比如下 方案1 記憶體一旦分配出去就無法 了。記憶體釋放函式是乙個空函式,什麼都沒做...

Libevent 2 1 8原始碼分析 記憶體管理

預設情況下,libevent使用c庫的記憶體管理函式在堆上分配記憶體 其實也就是我們在c中經常使用的malloc realloc和free 當然如果對於記憶體的管理有極高的要求,例如在我們的應用程式中可能頻繁的申請和釋放libevent相關的物件,如果採用預設的記憶體管理,那麼可能就會產生大量的記憶...