Увеличение PHP memory_limit. В какой момент это становится безумным?

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

Учитывая объем данных, загружаемых в массив, мы продолжаем использовать ограничение памяти. Он был увеличен несколько раз, и мне интересно, есть ли точка, в которой увеличение становится, как правило, плохой идеей? или это только вопрос того, сколько оперативной памяти у машины?

Аппарат имеет 2 ГБ ОЗУ, а memory_limit в настоящий момент установлен в 1,5 ГБ. Мы можем легко добавить больше ОЗУ к машине (и в любом случае).

Кто-нибудь сталкивался с такой проблемой? и каковы были решения?

Конфигурация для memory_limit PHP, работающего как модуль Apache на веб-страницах сервера, должна учитывать, сколько всего процесса Apache вы можете иметь одновременно на машине – см. MaxClients конфигурации MaxClients для Apache.

Если MaxClients 100 и у вас есть 2000 MB или RAM, очень быстрый расчет покажет, что вы не должны использовать более 20 МБ * (потому что 20 МБ * 100 клиентов = 2 ГБ или ОЗУ, т. Е. Общий объем памяти, ) * для значения memory_limit.

И это без учета того, что на одном сервере есть, вероятно, другие вещи, такие как MySQL, сама система … И этот Apache, вероятно, уже использует некоторую память для себя.

Или, конечно, это также «худший сценарий», который считает, что каждая страница PHP использует максимальный объем памяти, который он может.

В вашем случае, если вам нужен такой большой объем памяти только для одного задания, я бы не увеличил memory_limit для PḦP, работающего как модуль Apache.

Вместо этого я запустил эту работу из командной строки (или через задание cron) и задал бы более высокий параметр memory_limit в этом единственном случае.

Это можно сделать с помощью опции -d php, например:

 $ php -d memory_limit=1GB temp.php string(3) "1GB" 

Учитывая, что в этом случае temp.php содержит только:

 var_dump(ini_get('memory_limit')); 

На мой взгляд, это намного безопаснее, чем увеличение memory_limit для модуля PHP для Apache – и это то, что я обычно делаю, когда у меня есть большой набор данных или какой-то действительно тяжелый материал, который я не могу оптимизировать или разбивать на страницы.

Если вам нужно определить несколько значений для выполнения CLI PHP, вы также можете сказать ему использовать другой файл конфигурации вместо стандартного php.ini с параметром -c :

 php -c /etc/phpcli.ini temp.php 

Таким образом, у вас есть:

  • /etc/php.ini для Apache, с низким значением memory_limit , низким max_execution_time , …
  • и /etc/phpcli.ini для партий, запущенных из командной строки, практически без ограничений

Это гарантирует, что ваши партии смогут работать – и у вас по-прежнему будет безопасность для вашего сайта ( memory_limit и max_execution_time – меры безопасности)

Тем не менее, если у вас есть время для оптимизации вашего скрипта, вы должны; например, в такой ситуации, когда вам приходится иметь дело с большим количеством данных, разбиение на страницы является обязательным 😉

Вы пытались разбить набор данных на более мелкие части и обрабатывать только одну часть в то время?

Если вы извлекаете данные из файла диска, вы можете использовать функцию fread() для загрузки небольших фрагментов или какого- то небуферизованного db-запроса в случае базы данных.

Я не проверил PHP с v3.something, но вы также можете использовать форму облачных вычислений. 1 ГБ набор данных кажется достаточно большим, чтобы обрабатываться на нескольких машинах.

Учитывая, что вы знаете, что есть проблемы с памятью, связанные с вашим скриптом, которые нуждаются в исправлении, и вы ищете только краткосрочные решения, тогда я не буду обсуждать способы профилирования и решения ваших проблем с памятью. Похоже, вы доберетесь до этого.

Итак, я бы сказал, что основные вещи, которые вы должны иметь в виду:

  • Общая загрузка памяти в систему
  • Возможности ОС

PHP – это только один небольшой компонент системы. Если вы позволите ему съесть огромное количество вашей ОЗУ, тогда пострадают другие процессы, которые, в свою очередь, могут повлиять на сам сценарий. Примечательно, что если вы извлекаете большое количество данных из базы данных, то для создания наборов результатов для ваших запросов для вашей СУБД может потребоваться большая часть памяти. В качестве быстрого исправления вы можете захотеть идентифицировать любые выполняемые вами запросы и как можно скорее получить результаты, чтобы дать вам больше памяти для долгого прогона.

Что касается возможностей ОС, вы должны иметь в виду, что 32-разрядные системы, на которых вы, скорее всего, работаете, могут обращаться только до 4 ГБ ОЗУ без специальной обработки. Часто предел может быть намного меньше в зависимости от того, как он используется. Некоторые чипсеты и конфигурации на базе Windows могут иметь менее 3 ГБ в системе, даже с 4 ГБ или более физически установленными. Вы должны проверить, насколько ваша система может обращаться.

Вы говорите, что вы увеличили ограничение памяти несколько раз, поэтому, очевидно, эта работа становится все больше и больше по охвату. Если вы до 1.5 ГБ, то даже установка 2 ГБ больше оперативной памяти звучит так, как будто это будет короткая отсрочка.

Кто-нибудь сталкивался с такой проблемой? и каковы были решения?

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