Я использую 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()?
Возможно, просто чтение файла и его закрытие заставят ваш скрипт работать быстрее:
$this->file = file($file_path);
foreach ($this->file as $line) {
// do the thing you need to do
}
unset ($this->file);
Другое дело, что вы, кажется, читаете один массив ($file
) и превращаете его в другой ($line
). Может быть, стоит использовать массив $file
как есть?
Я не уверен, что вы делаете, но, надеюсь, эти предложения могут помочь.
array_shift() должен технически работать быстрее, чем больше он используется, так как он должен повторно индексировать меньший набор.
Вы делаете что-нибудь еще с возвращенным результатом?
Альтернативно, вы можете подумать об обращении массива до цикла:
$reversed = array_reverse($file);
А затем вытащить последнее значение внутри вашей циклы
$item = array_pop($reversed);