PHP7系列 核心陣列的優化(四)

2021-10-07 16:38:30 字數 2443 閱讀 8501

php原始碼中的陣列

php5的hashtable:

typedef

struct _hashtable hashtable;

typedef

struct bucket bucket;

hashtable的核心是儲存了乙個個指向zval指標的指標, 也就是zval**;

是zval**, 而不是zval*: 如果在符號表中存的是zval*,就做不到對一處修改, 所有的持有方都有感知。

php7的hashtable: 定義了乙個結構體叫做zend_array,alias為 hashtable

struct _zend_array  v;

uint32_t flags;

/* 通過 32 個可用標識,設定雜湊表的屬性 */

} u;

uint32_t ntablemask;

/* 雜湊值計算掩碼,等於ntablesize的負值(ntablemask = ~ntablesize + 1),計算最終落在那個bucket的值 */

bucket *ardata;

/* 用來儲存資料 bucket裡面存的是key-value對*/

uint32_t nnumused;

/* ardata 中的已用空間大小 */

uint32_t nnumofelements;

/* 雜湊表已有元素數 */

uint32_t ntablesize;

/* 雜湊表總大小,為2的n次方 */

uint32_t ninternalpointer;

/* 內部的指標,用於迭代(foreach) */

zend_long nnextfreeelement;

/* 下乙個可用的數值索引 如:arr = 1;arr["a"] = 2;arr = 3; 則nnextfreeelement = 2*/

dtor_func_t pdestructor;

/* 資料析構函式(控制代碼) */

};

雜湊演算法:通過key算出乙個雜湊值,然後以tablemask進行或運算,然後就可以保證元素雜湊到我們指定的bucket上

nindex = key->h | ntablemask;

而資料會核心儲存在ardata中,ardata是乙個bucket陣列,bucket定義:

typedef

struct _bucket bucket;

zend_array的記憶體占用從php5的72個位元組,降為56個位元組,極大的節省記憶體占用。

php7陣列都是有序存放:

雜湊表實現的關鍵是有乙個陣列儲存雜湊值與bucket的對映,但是hashtable中並沒有這樣乙個索引陣列。

實際上這個索引陣列包含在ardata中,索引陣列與bucket列表一起分配,ardata指向了bucket列表的起始位置,而索引陣列可以通過ardata指標向前移動訪問到,即ardata[-1]、ardata[-2]、ardata[-3]……索引陣列的結構是uint32_t,它儲存的是bucket元素在ardata中的位置。

整體來看hashtable主要依賴ardata實現元素的儲存、索引。插入乙個元素時先將元素插入bucket陣列,位置是idx,再根據key的雜湊值與ntablemask計算出索引陣列的位置,將idx存入這個位置;查詢時先根據key的雜湊值與ntablemask計算出索引陣列的位置,獲得元素在bucket陣列的位置idx,再從bucket陣列中取出元素。

原來hashtable為什麼要設計儲存zval**, 那麼php7因為_bucket直接儲存的是zval了,那怎麼解決cow的時候一處修改多處可見的需求呢?

is_indirect型別其實可以理解為就是乙個zval*的結構體。它被廣泛應用在globals,properties等多個需要倆個hashtable指向同於乙個zval的場景。

兩者對比現在的衝突拉鍊被bauck.zval->u2.next替代,於是bucket->pnext, bucket->plast可以去掉了。

zend_array->ardata是乙個陣列,所以也就不再需要plistnext, plistlast來保持順序了, 他們也可以去掉了。 現在陣列中元素的先後順序,完全根據它在ardata中的index順序決定,先加入的元素在低的index中。

php7中的bucket現在直接儲存乙個zval, 取代了php5時代bucket中的pdata和pdataptr。

最後就是php7中現在使用zend_string作為陣列的字串key,取代了php5時代bucket的*key, nkeylength。

PHP7核心剖析 PHP 函式

今天看一下php7中的函式相關的一點兒知識。首先來說,php的函式分為使用者自定義函式與內部函式兩類,先看一下使用者自定義函式。通過前面的文章,我們知道了php在編譯執行的時候,會將php指令碼解釋稱opline指令。那同樣的,php中函式也是被編譯成了opline指令集合zend op array...

讀《PHP7 核心剖析》

自己的書,在書上做筆記了。一本不錯的書,寫的算是詳細了。書中簡要介紹了各種功能的 c 語言實現的方法名稱。一,php 基礎架構 二,sapi 3 種執行 php 的方式。三,資料型別 四,記憶體管理 執行緒安全 五,php 編譯與執行 六,函式 七,物件導向 類的自動載入,255頁 autoload...

PHP7陣列底層原理

php底層是由hashtable bucket實現 hashtable typedef struct hashtable bucket typedef struct bucketbucket 二 儲存過程 通過hash函式對key做hash,算出在中間表的下標,資料順序的儲存在bucket陣列 鍊錶...