Правильно ли так экономить оперативную память?
Дано: Текстовый файл, скажем, с 1 000 000 строк (+-12 мб). Нужно прочитать этот файл построчно и обработать каждую строку. За один запуск скрипта файл может быть прочитан до 100 раз. Одновременно к файлу могут обращаться до 100 параллельных процессов, только на чтение, записи нет.
Работает это все в фоне, скорость не сильно важна.
Вариант 1:
$fp = fopen(__DIR__.'/memory_test.txt', 'rb');
if(is_resource($fp)){
for($i = 1; $i <=100; $i++){
while (!feof($fp)){
$line = trim(fgets($fp, 512));
//do something
}
rewind($fp);
}
fclose($fp);
}
Результат 1:
Done time: 11.448186159134
Memory peak usage: 421.52 kb
Вариант 2:
$fp = fopen(__DIR__.'/memory_test.txt', 'rb');
$lines = [];
if(is_resource($fp)) {
while (!feof($fp)) {
$lines[] = trim(fgets($fp, 512));
}
fclose($fp);
}
for($i = 1; $i <=100; $i++){
foreach($lines as $line){
//do something
}
}
Результат 2:
Done time: 0.78291392326355
Memory peak usage: 54 mb
Первый вариант заметно проигрывает в скорости, но выигрывает в использовании памяти, что с учетом того, что скрипт выполняется до 20 минут, время не критичное.
Второй вариант расходует заметно больше памяти, что, с учетом 100 параллельных процессов на таск, - весьма ощутимо, но как я подозреваю, меньше нагружает процессор.
Какой вариант предпочтительнее, что бы не уложить сервер на лопатки? Что можете предложить вы?
Спасибо.
Ответы (1 шт):
Загружать дисковую подсистему 100 кратным повторением чтения файла - это не лучший вариант, так как это бутылочное горлышко в системе. Поэтому предпочтительным будет второй вариант. 54 МБ по нынешним временам не так уж и много, а если всё-таки нужно экономить память, то тут можно придумать кой-какую оптимизацию.
Текстовый файл содержит много избыточной информации (10х), поэтому она может быть предварительно обработана, а потом размещена в памяти для последующего использования, что не только сэкономит память, но и улучшит производительность.