Рейтинг:0

Неожиданное увеличение использования памяти с PHP5 до PHP7 внутри контейнера

флаг ug

На прошлой неделе мы обновили несколько сайтов WordPress, на которых Alpine Linux работает как контейнеры внутри хоста (Ubuntu 20.04) через LXD.

Резюме обновления выглядит следующим образом:

Альпийский Linux v3.8 -> 3.14
PHP 5.3.6 -> 7.4.24
Вордпресс 5.0.3 -> 5.7.3

Проблема

У нас начались проблемы с производительностью сервера после этих обновлений, и мы обнаружили, что обновленные контейнеры использовали в 3 или более раз больше памяти (резидентной памяти), чем старые (около 150 МБ против 50 МБ), из-за чего сервер начал чаще подкачиваться.

В более старых версиях (использующих PHP 5.3) память, используемая php (процесс) увеличивается по мере обработки страницы (как и ожидалось), но сразу после ее завершения возвращается к нормальному состоянию. Другими словами, что-то вроде: 10 МБ ---> 95 МБ ---> 10 МБ.

В обновленных контейнерах память, используемая php увеличивается таким же образом, но не возвращается к «нормальному»: 10 МБ ---> 95 МБ ---> 95 МБ. И каждый раз, когда используется новый процесс, происходит то же самое, увеличивая использование памяти на количество доступных дочерних процессов (которых в данном случае 4 на сайт).

Что я пробовал

  • Понижение версии PHP до 7.2.х и 7.3.х : то же самое
  • Обновлено до PHP 8.0.11 : та же проблема
  • С использованием апач2 вместо лайтпд (в настоящее время php работает как fcgi): такое же поведение
  • Обновление только Alpine и PHP, чтобы определить, может ли быть причиной Wordpress: WordPress не является причиной
  • Запуск wordpress без плагинов (чтобы узнать, может ли какой-то плагин вызывать проблему): без изменений
  • Выполнил простой цикл конкатенации (чистый php): то же самое
  • Протестировано на другом сервере с другим сайтом WordPress: такое же поведение

По какой причине не восстанавливается память? Как это можно исправить?

Обновлять

  • я устанавливаю чистую Альпийский 3.14 контейнер и выполнил тест «простой цикл». В этом случае резидентная память была уменьшена, как и ожидалось. Однако, как только я протестировал реальный сайт WordPress, проблема осталась.
  • я устанавливаю чистую Убунту 20.04 контейнер и сделал те же тесты. Результат был такой же, как и при чистке. Альпийский 3.14.
флаг lr
Дублировано: https://stackoverflow.com/questions/39740398/i-am-facing-more-memory-consumption-in-php-7-compare-to-php-5-6
lepe avatar
флаг ug
@BarnabasBusa извините, я не думаю, что это связано с моей проблемой. При тестировании с помощью простого PHP-скрипта (конкатенация строк с циклом) на самом деле PHP7 занимает меньше памяти при запуске и выполнении простого теста. Проблема в том, что он не восстанавливает память после использования. Я также подозреваю, что это может быть связано с каким-то кешем (поскольку opcache включен по умолчанию в PHP7), но модуль opcache даже не установлен, и я также пытался отключить его в настройках.
lepe avatar
флаг ug
Отчет об ошибке: https://bugs.php.net/bug.php?id=81536 и связанный с ним: https://bugs.php.net/bug.php?id=80108.
Рейтинг:0
флаг ug

Согласно с этот отчет об ошибке на самом деле это не ошибка, а функция PHP7+ под Управление памятью Zend Engine:

[email protected] : это ожидаемое поведение. По запросу выключение Zend диспетчер памяти не освобождает все выделенные фрагменты, а сохраняет some[1], чтобы избежать необходимости их перераспределения, возможно, для следующего запрос.

Предлагаемое решение состоит в том, чтобы позвонить: gc_mem_caches(). Ты можешь использовать auto_prepend_file и auto_append_file директивы в php.ini выполнять его всегда, если это необходимо.

Однако это решение не помогло в моей ситуации, поэтому это не гарантия того, что оно сработает.

Поскольку в настоящий момент нет простого способа изменить это поведение, я нашел другой способ решить проблему с памятью (он должен работать для PHP7, PHP8):

  1. Вместо того, чтобы использовать php-cgi, использовать php-fpm
  2. Настройте конфигурацию FPM, чтобы использовать наименьшее количество дочерних процессов, но при необходимости позвольте ему создавать дочерние процессы, для этого вы можете либо использовать по требованию режим или динамичный:

/etc/php7/php-fpm.d/www.conf :

вечера = по требованию
; Отрегулируйте по мере необходимости:
pm.max_children = 10

или же:

вечера = динамический
; Отрегулируйте по мере необходимости:
pm.max_children = 10
pm.start_servers = 1
pm.min_spare_servers = 1
pm.max_spare_servers = 1

Основное различие между ними в том, что по требованию будет использовать меньше памяти в режиме ожидания, но будет медленнее при подключении клиента.

Это сравнение моих результатов:

PHP Режим Дети Максимум Простой мем. Макс Мем. Время загрузки Максимальное время*
PHP5 компьютерная графика 4 4 50 МБ 200 МБ 5 с 15 с
PHP7 компьютерная графика 4 4 200 МБ 200 МБ 5 с 30-е годы
PHP7 FPM / по запросу 0 10 15 МБ 500 МБ 7 с 10 с
PHP7 FPM / динамический 1 10 25 МБ 500 МБ 6 с 10 с
  • Максимальное время загрузки протестировано при одновременном запуске 50 клиентов.

Значения в таблице являются приблизительными и предназначены только для иллюстрации (ни в коем случае не являются реальным эталоном).

Ответить или комментировать

Большинство людей не понимают, что склонность к познанию нового открывает путь к обучению и улучшает межличностные связи. В исследованиях Элисон, например, хотя люди могли точно вспомнить, сколько вопросов было задано в их разговорах, они не чувствовали интуитивно связи между вопросами и симпатиями. В четырех исследованиях, в которых участники сами участвовали в разговорах или читали стенограммы чужих разговоров, люди, как правило, не осознавали, что задаваемый вопрос повлияет — или повлиял — на уровень дружбы между собеседниками.