Редактировать : Первоначально я думал, что эта проблема связана с PHP-FPM, потому что мой хост подразумевал это (см. Ниже).Я нашел способ настроить мой тестовый сервер на использование PHP-FPM (cgi-fcgi), и скрипт работал без проблем с производительностью и памятью.Возможно, на сервере моего хоста есть что-то еще, что делает странные вещи, такие как отслеживание записей в файлах и запись записанного содержимого в память без причины.Кто-нибудь знает, есть ли такое программное обеспечение / модули, которые могли бы сделать это?Тем временем я снова свяжусь с моим хостом ...
Проблема
У меня есть PHP-скрипт, который записывает данные в файл, используя fwrite()
.На моем виртуальном хостинге, на котором работает сервер CloudLinux, производительность снижается, а память исчерпывается, когда требуется много данных.Кажется, проблема в PHP-FPM, который Apache использует на сервере.Если я подключаюсь к серверу по SSH и запускаю тот же сценарий с PHP-CLI, производительность становится намного лучше (до 7 раз быстрее), а использование памяти остается более или менее одинаковым на протяжении всего сценария.
Iнаписал простой тестовый скрипт, чтобы проиллюстрировать это:
echo 'SAPI: ' . php_sapi_name(); // Shows if you're using fcgi or cli
if (php_sapi_name() === 'cli') { // Set appropriate line break char
$eol = PHP_EOL;
}
else {
$eol = '<br>';
}
echo $eol;
echo 'Starting fwrite...' . $eol;
$time_start = microtime(true);
$fh = fopen('/some/path/test-fw.txt', 'w');
$i = 0;
while ($i < 2000000) {
$str = 'row-' . $i . ': this is a test string abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg ';
fwrite($fh, $str);
$i++;
}
echo 'fwrite done!' . $eol;
echo 'Time taken: ' . (microtime(true) - $time_start) . 's' . $eol;
fclose($fh);
echo 'Sleeping for 60s before exiting...';
sleep(60); // Give you some time to check memory usage (in CPanel)
Результаты теста:
- При вызове из браузера использование памяти начинается с 30 МБ и к концу возрастает до ~ 330 МБ.сценария.Время выполнения составляет около 78 секунд.
- При вызове с помощью PHP-CLI использование памяти остается на уровне около 30 МБ.Время выполнения составляет около 10 секунд.
Использование памяти - это использование физической памяти, показанное на CPanel.Кстати, размер файла составляет около 300 МБ, поэтому я подумал, если бы содержимое, написанное с помощью fwrite (), также было помещено в память PHP-FPM!
Я надеялся обойти эту проблему, выполнив exec('php-cli script.php')
в другом сценарии, но это не сработало.Все, что он сделал, это создал php-cli
процесс как потомок процесса php-cgi
.
Служба поддержки моего хоста сказала мне, что "CGI помещает все в память, если вы не скажетеэто "сбросить" его, и CGI разработан, чтобы быть менее интенсивным процессором ".Я был несколько озадачен, потому что я не мог видеть, что там можно «сбросить» в моем коде, чтобы освободить память.Я имею в виду, что в моем тестовом скрипте CGI хранит каждый $str
, переданный fwrite()
, если я не запрещаю это явно?Если да, то как мне это сделать (пробовал unset()
, что не помогло)?
К сожалению, я не смог изменить обработчик PHP на виртуальном хостинге.В противном случае, я бы просто использовал mod_php, который я сейчас использую на своем локальном тестовом сервере, без заявленных проблем.
Интересно, есть ли у кого-нибудь подобный опыт, который мог бы указать мне правильное направление.Если это имеет какое-либо значение, я использую план питания Inmotion Hosting, в котором для моей учетной записи выделено 2 ГБ физической памяти.
Чтобы уточнить: память, похоже, откатилась назадк норме вскоре после вызова fclose()
и начала периода сна.Так что я думаю, что fwrite()
вызывает эту странную проблему.fflush()
и set_file_buffer($fh, 0)
не помогли.Как будто контент записывается на диск, но в то же время сохраняется в памяти, и я не знаю, что является причиной последнего ...