我正在使用php脚本来更新产品数据。 虽然消耗的内存是不变的,但每1000个产品的消耗时间一直在增加:
[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行的文件来说不是理想的解决方案,并且必须每天更新。
至少可以理解这里发生的事情......
提前感谢任何提示。
答案 0 :(得分:3)
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的垃圾收集
答案 1 :(得分:0)
array_shift()在技术上运行得越快,因为它必须重新索引一个较小的集合。
您是否正在使用返回的结果执行其他操作?
或者,您可以考虑在循环之前反转数组:
$reversed = array_reverse($file);
然后弹出循环中的最后一个值
$item = array_pop($reversed);
答案 2 :(得分:0)
是否有特定原因需要使用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
数组?
我不确定你到底在做什么 - 但希望这些建议可能有所帮助。