我有这个PHP代码(版本5.4)读取6MB文本文件并将其拆分为行,然后按标签拆分这些行:
echo "Initial memory used: ".memory_get_usage()." bytes.\n";
$data = file_get_contents(ENROLLMENTS_SRC_PATH);
echo "About to split into lines, current memory used: ".memory_get_usage()." bytes.\n";
$data = explode("\n", $data);
echo "About to split lines into columns, current memory used: ".memory_get_usage()." bytes.\n";
$line = explode("\t", $data[0]);
echo "Split one line, current memory used: ".memory_get_usage()." bytes.\n";
echo "Peak memory used so far: ".memory_get_peak_usage()." bytes.\n";
foreach($data as $key => $line) {
$data[$key] = explode("\t", $line);
}
echo "Final memory used: ".memory_get_usage()." bytes.\n";
echo "Peak memory used: ".memory_get_peak_usage()." bytes.\n";
据我所知,PHP数组的开销非常高,但根据这些结果,我并不期望foreach循环中的峰值使用量比最终结果大约28MB:
Initial memory used: 226384 bytes.
About to split into lines, current memory used: 6536952 bytes.
About to split lines into columns, current memory used: 18327712 bytes.
Split one line, current memory used: 18328352 bytes.
Peak memory used so far: 24639744 bytes.
Final memory used: 116898184 bytes.
Peak memory used: 135000584 bytes.
这是如此之大,以至于峰值内存高于循环前和循环组合后$data
使用的内存,即使单个分割线的大小似乎低于千字节。我试图减少我的脚本使用的内存,所以我试图了解PHP如何使用内存。
为什么foreach
循环使用了这么多明显多余的内存,我能做些什么呢?
答案 0 :(得分:0)
大多数超额记忆背后的解释都在this explanation of the workings of foreach
中找到,这解释了foreach
适用于"副本"数组。该副本实际上是一个写时复制,其中只有在/修改数组时才会发生重复。由于这个foreach循环确实修改了原始数组,因此它会创建一个循环的副本,这解释了大部分额外的28MB。
有几种方法可以防止这种情况,包括使用除foreach
之外的任何其他循环,或使用如下引用:
foreach($data as &$line) {
$line = explode("\t", $line);
}
unset($line)
当循环的数组或包含数组条目的变量是引用时,不会进行重复。但是,重要的是取消设置$line
以防止在循环运行后意外修改数组的内容。