大型 PHP 5.4 脚本变慢


Large PHP 5.4 Script gets slower

我正在使用 php 脚本来更新产品数据。虽然消耗的内存是恒定的,但每 1.000 个产品的消耗时间一直在增加:

[26000 - 439.75 MB / 14.822s]..........
[27000 - 439.25 MB / 15.774s]..........
[28000 - 438.25 MB / 15.068s]..........
[29000 - 437.75 MB / 16.317s]..........
[30000 - 437.25 MB / 16.968s]..........
[31000 - 436.25 MB / 17.521s]....

即使我禁用了除读取包含 CSV 数据的变量行之外的所有内容,效果也是一样的,只是增长率较低:

[65000 - 424.75 MB / 0.001s]..........
[66000 - 424.75 MB / 0.63s]..........
[67000 - 424.75 MB / 0.716s]..........
[68000 - 424.75 MB / 0.848s]..........
[69000 - 424.75 MB / 0.943s]..........
[70000 - 424.25 MB / 1.126s]..........
[71000 - 423.5 MB / 1.312s]....

我尝试更改GC设置(php -dzend.enable_gc = 1和php -dzend.enable_gc= 0)。

我提前加载数据:

$this->file = file($file_path);

下一行的检索方式为:

$line = array_shift($this->file);

我不知道为什么这应该持续增加所需的时间,尤其是当我只是array_shift行而不对其执行任何操作时。

我目前的解决方案是将文件拆分为 10.000 个部分,对于包含超过 300.000 行且必须每天更新的文件来说,这不是一个理想的解决方案。

至少了解这里发生的事情会很好......

提前感谢您的任何提示。

array_shift() 的问题

数组中每个元素的内部维护的部分数据是标识该元素在数组中位置的序列号。这些值实际上是连续整数,从第一个元素的 0 开始。不要将其与枚举数组的键值混淆,它纯粹在内部维护,并且与键完全分开,以便您可以进行关联排序,这实际上只是重新组织这些内部位置值。

向数组添加新元素时,需要为其指定新的序列值。如果您只是将新元素添加到数组的末尾,那么就像获取以前的最高序列值,添加一个并将其分配为新元素的序列值一样简单。一个简单的 O(1) 活动。同样,如果删除最后一个元素,则可以简单地将其删除,并且所有其他元素的序列仍然有效。

但是,如果使用 array_unshift() 将一个新元素添加到数组的开头,那么它将被分配 0 值,并且数组中已有的每个现有元素都需要将其序列值增加 1,因此 PHP 在内部必须遍历每个元素,使其成为 O(n) 事务。同样,array_shift() 必须在从数组中删除第一个元素(也是 O(n))后,为每个剩余的数组元素指定序列值。如果阵列非常大,这可能是一个主要的开销。

一般性能

为了回答您的性能问题....为什么要一次性将整个文件读入内存?为什么不能简单地一次处理一行?

$fh = fopen('filename.txt', 'r');
while (!feof($fh)) {
    $item = fread($fh);
    .... processing here
}
fclose($fh);

不要试图超越PHP的垃圾收集

array_shift() 在技术上应该运行得越快,因为它必须重新索引较小的集合。

您是否对返回的结果执行其他操作?

或者,您可以考虑在循环之前反转数组:

$reversed = array_reverse($file);

然后在循环中弹出最后一个值

$item = array_pop($reversed);

是否需要使用 array_shift() 的特定原因?

也许只是读取文件并关闭它会让你的脚本运行得更快:

$this->file = file($file_path);
foreach ($this->file as $line) {
  // do the thing you need to do
}
unset ($this->file);

另一件事是你似乎正在读取一个数组($file)并将其转换为另一个数组($line)。也许值得按原样使用 $file 数组?

我不确定你在做什么 - 但希望这些建议可能会有所帮助。