PHP 7.2 中 array_fill 处理百万级数组易 OOM,应改用生成器按需产出:function idSequence(int $count): Generator { for ($i = 1; $i <= $count; $i++) yield $i; }

PHP 7.2 中 array_fill 虽能快速生成定长数组,但直接用于超大长度(如百万级)时,会一次性分配全部内存,极易触发 OOM 或拖慢响应。关键不是“能不能填”,而是“要不要全装进内存”。优化核心是:避免全量构造、减少哈希开销、按需供给。
优先用生成器替代全量 array_fill
若后续只是遍历处理(如批量写库、逐条计算),根本无需把整个数组存在内存里。
- 用
yield写一个轻量生成器,每次迭代只产出一个值,内存占用恒定在 KB 级 - 示例:代替
$ids = array_fill(0, 1000000, 0);
for ($i = 1; $i yield $i;
}
}
然后 foreach (idSequence(1000000) as $id) { ... } —— 内存不随长度增长。
必须用数组时,选对类型和键结构
PHP 数组本质是哈希表,每个元素带引用计数、类型标记等元数据。100 万个整数用 array_fill(0, 1000000, 0) 在 64 位系统下实际占约 100–150 MB,远超理论值。
立即学习“PHP免费学习笔记(深入)”;
- 确认是否真需要“关联数组”:如果只是纯数字索引容器,且长度已知、极少增删,改用
SplFixedArray -
$arr = new SplFixedArray(1000000);内存可降 40%+,且访问更快(连续内存 + 无哈希查找) - 避免字符串键:
array_fill_keys(range(1, 1000000), '')会生成字符串键,比整数键多占 2–3 倍内存
控制填充粒度,分批处理
即使要用 array_fill,也不必一次填完百万项。
- 拆成每批 10000~50000 个,处理完一批就
unset,再建下一批 - 配合
gc_collect_cycles()主动触发垃圾回收(尤其在循环中反复新建大数组时) - 注意:
unset($arr)不等于立刻还内存给系统,需确保无其他变量引用该数组
检查是否真需要预填充
很多场景所谓“初始化数组”,其实只是为了占位或防止 undefined index 报错。
- 用
??或isset()替代预设默认值,更省内存 - 用
array_pad([], $len, $default)比array_fill更灵活,但同样有内存代价,慎用于超大 $len - 若只是做查找映射,考虑用
array_flip构建键值倒置索引,但注意它本身也会复制原数组——仅适用于原数组已存在且不可改的情况



















