Вопрос или проблема
У меня есть веб-сервер Apache 2.2 с FastCGI и PHP 5.3, я установил лимит памяти в 256МБ в php.ini и с помощью php-cgi -i получил 256МБ. Таким образом, конфигурация правильная, мой процесс успешно читает это значение. Я упомянул это, потому что читал много постов в интернете, где проблема заключалась в неправильном расположении php.ini. В моем случае я уверен, что всё верно.
Мои процессы php-cgi 8 плюс родитель выделяют RSS больше 256МБ, некоторые процессы выделяют даже 700МБ без проблем. Почему?
Какова природа лимита памяти, если некоторые процессы php-cgi могут выделять больше 256МБ?
Я пытался найти какую-либо ошибку, но ничего не нашел.
Мое приложение не использует ini_set для переопределения параметра memory_limit, так что я уверен, что лимит в 256МБ должен соблюдаться.
Настройка PHP memory_limit
является виртуальным лимитом памяти. RSS — это показатель физического использования памяти. Они имеют очень мало общего друг с другом.
Настройка memory_limit
устанавливает количество виртуальной памяти, которую PHP-скрипт имеет право выделить непосредственно. Это не предел для процесса и это не предел физической памяти.
Мои процессы php-cgi 8 плюс родитель выделяют RSS больше 256МБ, некоторые процессы выделяют даже 700МБ без проблем. Почему?
Вы сказали, что используете FastCGI на вашем веб-сервере, так что я предполагаю, что вы запускаете PHP через PHP-FPM, а не PHP-CGI.
Вы не сказали, к какой операционной системе это относится (это довольно важный момент, когда речь идет об управлении памятью).
Он не выделяет столько памяти — он только отображает столько памяти. Для краткого объяснения различия и почему это важно, вы должны прочитать это.
Ответ Дэвида почти правильный — memory_limit это предел на количество памяти, которое может быть выделено для среды выполнения сценария, сам скрипт, если он не находится в кэше опкод, (и первая компиляция кода) вместе с пространством, выделенным для хранения PHP переменных во время выполнения.
В случае выполнения PHP-кода уже находящегося в кэше опкод, я не знаю, учитываются ли страницы в кэше опкод в использовании, ограниченном memory_limit — и потребовалось бы много усилий на исходный код PHP, чтобы это выяснить.
У меня установлен лимит памяти в 256МБ в php.ini
Это довольно высоко. Поскольку вы не понимаете, как работает управление памятью, мне интересно, почему. Установка лимита слишком высоко ограничивает возможности вашей системы. Выполнение PHP с радостью заполняет пространство до memory_limit. Когда память становится недостаточной, запускается сборка мусора и освобождает место, занятое мертвыми (неиспользуемыми) данными. Если память никогда не становится ограниченной, сборка мусора никогда не происходит.
Как здесь представлено, это не похоже на вопрос об управлении информационными системами в бизнес-среде. Вы сказали в комментариях, что:
Моя проблема в том, что RSS процесса php-cgi неограничен
Но он ограничен лимитом памяти в php.ini. Если вы мне не верите, напишите скрипт, который будет занимать данные, и вы увидите, что в какой-то момент он упадет.
Если вы действительно хотите узнать, как планировать и управлять мощностями системы, то это совершенно другой вопрос — и вы не попробуете ответить на него, глядя на RSS и VSZ.
процессы не убиваются oom-killer, php-cgi начинает использовать своп и замедляет мою систему
Наконец-то! Правильное постановка проблемы!
Почему у вашей системы есть своп, если вы не собираетесь его использовать? Вышеупомянутый линк даст вам несколько советов по настройке вашей системы, чтобы это не происходило. Если это многопользовательская система, где другим приложениям действительно требуется своп, то вы можете разделить их на виртуальные машины или контейнеры.
Ответ или решение
Вопрос, с которым вы столкнулись, связан с настройками памяти в PHP и тем, как они соотносятся с фактическим выделением памяти процессами. Вы упомянули, что у вас установлен лимит памяти в 256 МБ в файле php.ini и что ваш сервер (Apache 2.2 с FastCGI и PHP 5.3) корректно воспринимает эту настройку. Однако некоторые процессы PHP-CGI функционируют с использованием намного больше памяти, чем это значение, и вызывают замедление системы.
Понимание лимита памяти PHP
Важно понимать, что параметр memory_limit
в PHP — это виртуальный предел, который ограничивает объем памяти, который PHP-скрипт может непосредственно выделить во время выполнения. Этот лимит не является физическим лимитом и не ограничивает общий объем памяти, который может использоваться процессом как таковым.
Физическая память, отображаемая в RSS (Resident Set Size), не имеет прямого отношения к лимиту памяти PHP. RSS содержит как выделенную память (для выполнения вашего кода), так и память, используемую для кэша и других системных нужд. Это значит, что даже если скрипт PHP должен остановиться при достижении лимита в 256 МБ, фактическое использование памяти, отображаемое в RSS, может быть значительно выше, так как ОС и сервер могут выделять дополнительные ресурсы для оптимизации работы.
Объяснение вашего случая
Ваше замечание о количестве выделенной памяти (700 МБ) предполагает, что:
- Ваши скрипты могут использовать кэшированные данные, которые не будут учитывать в лимите памяти, установленном php.ini.
- Возможно использование высокого количества памяти связано с другими процессами и кэшем, созданным вашим веб-сервером, а не только с выполняемыми PHP-скриптами.
Рекомендации по управлению памятью
-
Оптимизация вашего кода: Проверьте, не использует ли ваш код избыточное количество памяти. Это может происходить из-за рендеринга большого объема данных в память или от хранения больших массивов.
-
Петровикация и GC: Убедитесь, что у вас правильно настроена сборка мусора (garbage collection). PHP освобождает память только тогда, когда это необходимо; если ваш код работает с высоким мемориальным лимитом, это может привести к тому, что память будет заполняться, но не освобождаться.
-
Мониторинг и управление ресурсами: Применение инструментов мониторинга (например,
top
,htop
, илиNewRelic
) поможет вам получить более детальное представление о том, как используется память на вашем сервере. -
Рассмотрите PHP-FPM: Если вы используете FastCGI, рассмотрите возможность перехода на PHP-FPM, который более эффективно управляет пулами процессов. Это позволитуглить нагрузку на память лучше.
-
Конфигурация свопа: Поскольку вы упомянули проблемы со свопом, убедитесь, что ваша система настроена таким образом, чтобы использовать своп только в необходимых случаях. Если своп используется из-за высокой нагрузки, рекомендуется добавить физической памяти в систему.
Заключение
Таким образом, лимит памяти в PHP контролирует лишь ту часть памяти, которую может выделить скрипт, однако фактическое использование системы может быть намного более объемным из-за различных факторов. Управление памятью — это комплексная задача, требующая внимания к особенностям исполнения и структуры вашего кода, а также необходимой настройки на уровне системы.