摘要:但在多線程模式下會有多個,也就是說每個線程都有一個獨立的內存池內存分配分配超過內存的申請,與通用的內存申請沒有太大差別,只是將申請的內存塊通過單鏈表進行了管理。的分配實際就是分配多個,的分配也是內存分配的基礎,它是向系統申請內存的唯一粒度。
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結構。但在多線程模式下(ZTS)會有多個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)置為1
Small分配
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]指向釋放的內存,也就是將釋放的內存插到鏈表頭部
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/28584.html
摘要:插入一個元素時先將元素按先后順序插入數組,位置是,再根據的哈希值映射到散列表中的某個位置,將存入這個位置查找時先在散列表中映射到,得到在數組的位置,再從數組中取出元素。目前只有兩種類型會使用這種機制。 1.變量結構 typedef struct _zval_struct zval; typedef union _zend_value { zend_long ...
摘要:中專門為解決線程安全的問題抽象出了一個線程安全資源管理器,實現原理比較簡單既然共用資源這么困難那么就干脆不共用,各線程不再共享同一份全局變量,而是各復制一份,使用數據時各線程各取自己的副本,互不干擾。 1.線程安全資源管理器 PHP的SAPI多數是單線程環境,比如cli、fpm、cgi,每個進程只啟動一個主線程,這種模式下是不存在線程安全問題的,但是也有多線程的環境,比如Apache,...
摘要:是與之間數據交換的一種協議。當收到這個請求后,會啟動對應的程序,這里就是的解析器。接下來解析器會解析文件,初始化執行環境,然后處理請求,再以規定規定的格式返回處理后的結果,退出進程,再把結果返回給瀏覽器。 CGI:是 Web Server 與 Web Application 之間數據交換的一種協議。FastCGI:同 CGI,是一種通信協議,但比 CGI 在效率上做了一些優化。PHP-...
摘要:是與之間數據交換的一種協議。當收到這個請求后,會啟動對應的程序,這里就是的解析器。接下來解析器會解析文件,初始化執行環境,然后處理請求,再以規定規定的格式返回處理后的結果,退出進程,再把結果返回給瀏覽器。 CGI:是 Web Server 與 Web Application 之間數據交換的一種協議。FastCGI:同 CGI,是一種通信協議,但比 CGI 在效率上做了一些優化。PHP-...
摘要:是與之間數據交換的一種協議。當收到這個請求后,會啟動對應的程序,這里就是的解析器。接下來解析器會解析文件,初始化執行環境,然后處理請求,再以規定規定的格式返回處理后的結果,退出進程,再把結果返回給瀏覽器。 CGI:是 Web Server 與 Web Application 之間數據交換的一種協議。FastCGI:同 CGI,是一種通信協議,但比 CGI 在效率上做了一些優化。PHP-...
閱讀 3747·2023-04-25 18:41
閱讀 1180·2021-11-11 16:55
閱讀 1840·2021-09-22 15:54
閱讀 3075·2021-09-22 15:51
閱讀 3551·2019-08-30 15:55
閱讀 1947·2019-08-30 14:19
閱讀 1287·2019-08-29 10:57
閱讀 1708·2019-08-29 10:56