PHP7.4 64位环境下简单变量内存占用远超预期问题咨询
测试代码与运行结果
你提供的测试代码如下:
$datetimes = []; $memory_before = memory_get_usage(); for ($x = 0; $x < 1000; $x++) { $datetimes[] = new \DateTime(); } var_dump('DateTimes: ' . (memory_get_usage() - $memory_before)); $ints = []; $memory_before = memory_get_usage(); for ($x = 0; $x < 1000; $x++) { $ints[] = $x; } var_dump('Integers: ' . (memory_get_usage() - $memory_before));
64位PHP 7.4环境运行输出:
string(17) "DateTimes: 350504" string(15) "Integers: 37160"
内存占用偏高的核心成因
该现象属于PHP底层实现的正常设计,并非异常,主要来自两部分开销:
zval变量封装开销
PHP是弱类型动态语言,所有变量统一用zval结构体存储,64位PHP 7+版本中单个zval固定占用16字节,除存储实际数值外,还需要携带变量类型标记、引用计数等附加信息,即便是整型也无法直接使用原生8字节存储,本身就比预期占用高一倍。数组哈希表的额外开销
PHP普通数组底层为哈希表(HashTable)实现,为支持随机查找、关联/索引键混用、动态扩容等特性,每个数组元素对应一个Bucket结构体,64位下单个Bucket固定占用32字节,结构如下:
typedef struct _Bucket { zval val; // 16字节,存储变量内容 zend_ulong h; // 8字节,存储元素的哈希值 zend_string *key; // 8字节,存储关联键指针(索引数组时为空) } Bucket;
同时哈希表为降低哈希冲突概率,槽位数量始终取大于元素数量的最小2次幂,槽位本身是指针数组,每个指针占8字节。
按1000个整型元素计算:
- 1000个Bucket共占用:1000 * 32 = 32000字节
- 槽位(大于1000的最小2次幂为1024)共占用:1024 * 8 = 8192字节
- 加上哈希表基础结构开销,总占用和你测试的37160字节完全吻合。
百万级元素时的内存占用也和上述计算逻辑成正比,属于正常情况。
低内存存储方案
如果需要存储大量纯索引的同类型数据,可使用SplFixedArray代替普通数组,它是固定长度的顺序存储结构,省去了哈希表的Bucket和空槽位开销,内存占用可降低70%以上。
内容的提问来源于stack exchange,提问作者olidem
相关产品推荐
相关产品推荐

