Время выполнения итераций постоянно растёт
Добрый вечер дорогие пользователи,
Нужна ваша помощь, я написал, грубо говоря, воркер, который берёт данный из файла используя следю команду tail -n+x path/to/file | head -n50, но при каждой повторной итераций время выполнения скрипта увеличивается
Пример кода:
$p = 'UploadFiles/million_test.txt';
$l = 0;
$i = 0;
$start = microtime(true);
do {
$command = "tail -n+$l $p | head -n50";
exec($command, $data);
$count = count($data);
if ($count == 0) {
die;
}
$i++;
$l += 500;
if ($i % 100 == 0) {
file_put_contents(
'test.txt',
"$l [$count] =>" . round((microtime(true) - $start), 2) .
PHP_EOL,
FILE_APPEND
);
$start = microtime(true);
}
unset($data);
} while ($count > 0);
Данные выполнения скрипта
50000 [50] =>0.71
100000 [50] =>0.9
150000 [50] =>1.09
200000 [50] =>1.19
250000 [50] =>1.35
300000 [50] =>1.44
350000 [50] =>1.58
400000 [50] =>1.66
450000 [50] =>1.65
Как вы можете видеть, спустя пару итераций время выполнение скрипта увеличивалось в 2 раза.
Может кто-то знает что я делаю не так?
Или хотя-бы дайте намёк что на почитать, буду очень плагодарен.
В файле million_test.txt около 12 миллионов записей.
Ответы (2 шт):
В общем-то это все объяснимо. Вероятней всего время итерации увеличивается из-за того что дольше работает команда tail. Т.е. тут проблема не вашем коде, а в том как tail работает.
Т.е. когда вы "просите" выдать вам последние 500 строк из файла, то команда считывает эти 500 строк и выводит. Когда вы просите выдать следующие 500 строк, то команда считывает 1000 строк и выводит их, а потом через head вы берете из них только пятьсот.
На следующей итерации tail считывает уже 1500 строк. И т.д. и т.п. Чем ближе к началу файла, тем больше строк нужно считать и выдать, тем дольше работает команда.
В данной реализации с этим ничего не поделать. Не совсем понятно какую вы задачу решаете. Но возможно более оптимально и быстро будет открыть этот файл средствами PHP и построчно его прочитать за один раз. И разбить на блоки, если это нужно. Или сделать что-то еще.
$command = "tail -n+$l $p | head -n50";
exec($command, $data);
команда считывает из файла все(-n+$l) строк, а потом берет верхнюю их часть(-n50)
сам подход очень медленный.
file($p) для этого подойдет много лучше, ниже сравнительный тест по скорости чтения сгенерированого файла на 1м строк
весь файл прочитан функцией file($p) за 0.01сек
далее произведено чтение файла по частям при помощи exec("trail ....")
Array
(
[50_5000] => 0.03
[50_10000] => 0.03
[50_15000] => 0.03
[50_20000] => 0.03
[50_25000] => 0.03
[50_30000] => 0.03
[50_35000] => 0.04
[50_40000] => 0.04
[50_45000] => 0.04
[50_50000] => 0.04
[50_55000] => 0.04
[50_60000] => 0.04
[50_65000] => 0.04
[50_70000] => 0.04
[50_75000] => 0.05
[50_80000] => 0.05
[50_85000] => 0.05
[50_90000] => 0.05
[50_95000] => 0.05
[50_100000] => 0.05
)