php array 底层实现
PHP 数组的底层实现
PHP 数组是一种混合数据结构,既支持数字索引也支持字符串键(关联数组)。其底层实现基于哈希表(HashTable)和双向链表,以下是具体细节:
哈希表结构
PHP 数组的核心是 zend_array(PHP 7+)或 HashTable(PHP 5),通过哈希表实现高效键值存储。哈希表使用开放寻址法解决冲突,动态扩容以保证性能。
- 哈希函数:将键(字符串或数字)转换为哈希值,确定存储位置。
- 桶(Bucket):存储键值对,包含键、值、哈希值及链表指针。
有序性实现
PHP 数组保持插入顺序,通过双向链表维护。每个桶包含 pListNext 和 pListLast 指针,指向下一个和上一个元素。
动态扩容
哈希表会根据元素数量动态调整大小:
- 当填充因子(元素数/桶数)超过阈值(默认 0.5),触发扩容。
- 新容量为当前容量的 2 倍,重新哈希所有元素。
内存管理
PHP 7 优化了内存布局,减少间接访问:
- 内联存储值(
zval直接存储在桶中,而非指针)。 - 减少内存碎片,提升缓存命中率。
性能特点
- 平均时间复杂度:插入、删除、查找均为 O(1)。
- 最坏情况:哈希冲突严重时退化至 O(n)。
- 内存占用:PHP 7 相比 PHP 5 减少约 50%。
示例代码结构
以下是简化版底层结构的伪代码表示:
struct _zend_array {
uint32_t nTableSize; // 哈希表大小
uint32_t nNumUsed; // 已用桶数
uint32_t nNumOfElements; // 实际元素数
Bucket *arData; // 桶数组
uint32_t *arHash; // 哈希索引数组
};
struct Bucket {
zval val; // 存储的值
zend_ulong h; // 哈希值
zend_string *key; // 字符串键
Bucket *pListNext; // 下一个元素(有序)
Bucket *pListLast; // 上一个元素(有序)
};
实际应用建议
- 预分配大小:使用
array_fill(0, $size, null)减少扩容开销。 - 避免混合键类型:数字键和字符串键混用可能导致性能下降。
- 引用传递:PHP 7+ 的数组赋值默认写时复制(COW),修改时才会复制。
通过这种设计,PHP 数组在灵活性和性能之间取得了平衡,适用于大多数应用场景。







