Hash 演算法是 PHP 陣列、物件屬性、符號表等核心資料結構的基石。本文梳理 PHP 歷代雜湊函式演進、原理與實作細節。
經典字串雜湊函式,源自 Daniel J. Bernstein:
// C 實作
static inline zend_ulong zend_inline_hash_func(const char *str, size_t len) {
zend_ulong hash = 5381;
for (size_t i = 0; i < len; i++) {
hash = ((hash << 5) + hash) + str[i]; // hash * 33 + c
}
return hash;
}
特點:計算快、分佈均勻、對短字串極佳。PHP 5 陣列、符號表皆採用此演算法。
PHP 7 引入 zend_string 結構,預先計算並快取雜湊值:
struct _zend_string {
zend_refcounted_h gc;
zend_ulong h; // 預計算的雜湊值
size_t len;
char val[1]; // 實際字串內容
};
優勢:
h,避免重複計算。PHP 7 採用「線性探測」+「雙重雜湊」混合策略:
// 簡化邏輯
idx = hash & mask; // mask = table_size - 1
while (bucket[idx].key != key) {
if (bucket[idx].key == NULL) { /* 空位,插入 */ }
idx = (idx + 1) & mask; // 線性探測下一格
}
配合「墓碑」標記處理刪除,避免查找鏈中斷。
PHP 5.4+ 引入隨機種子 zend_hash_seed,每次啟動產生不同雜湊基數,防止惡意構造碰撞鍵導致效能退化(HashDoS 攻擊)。
array_fill_keys() 預先建立大小,減少擴容次數。