array_shift()性能差的根本原因是php数组底层为有序哈希表,删除首元素需o(n)级索引重排;而array_pop()仅减计数器,为o(1)操作。

大数组用 array_shift() 性能差,根本原因在于 PHP 数组的底层是有序哈希表,不是连续内存的线性数组。它支持灵活的索引(数字+字符串),但牺牲了头部操作的效率。
底层结构导致必须重排索引
PHP 数组内部维护一个连续存储元素的 arData 数组,同时用一张映射表记录每个键在 arData 中的位置。当你调用 array_shift():
- 它要删除索引为
0的元素(通常是第一个插入的数值键) - 然后把原来索引
1的元素挪到位置0,2挪到1……直到最后一个元素 - 所有剩余元素的数字索引都要重新编号,
nNumOfElements减 1,nNextFreeElement不变
这个过程不是指针偏移,而是实实在在的内存块逐个移动,时间复杂度为 O(N)。10 万个元素的数组,一次 array_shift() 就要移动近 10 万次。
哈希表设计不优化“首删”场景
PHP 数组的哈希结构重点保障的是:按插入顺序遍历 和 任意键随机访问,而不是队列式 FIFO 操作:
- 没有单独维护“头指针”或“尾指针”
- 没有为头部删除预留空间或反向索引机制
- 字符串键保持不变,但数字键必须连续,强制触发重索引
也就是说,它本质上不是为队列设计的——只是我们用 array_push() + array_shift() “模拟”队列,却承担了不该有的开销。
对比:为什么 array_pop() 很快?
array_pop() 只需:
- 读取并返回最后一个元素
- 将
nNumOfElements减 1 - 不改变其他任何元素的位置或索引
整个操作是 O(1),完全避开重排。这也是为什么真要用队列,推荐 SPL 的 SplQueue;要用栈,array_push()/array_pop() 就足够高效。











