Как остановить выходной буфер PHP от превышения лимита памяти? - PullRequest
2 голосов
/ 11 ноября 2008

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

ob_start()
//Business Logic, etc
header->output();
echo apply_post_filter(ob_get_clean());
footer->output();

Это гарантирует, что ошибки PHP будут отображаться в контентной части веб-сайта, и что ошибки не мешают вызовам header и session_*.

Моя единственная проблема в том, что на некоторых больших страницах PHP не хватает памяти. Как я могу предотвратить это?

Некоторые идеи:

  1. Запишите весь буферизованный контент во временный файл и выведите его.
  2. Когда буферы достигнут определенного размера, выведите его. Хотя это может помешать постфильтру.
  3. Повысить предел памяти (спасибо @troelskn).

В чем недостатки каждого из этих подходов? Особенно повышение лимита памяти?

Ответы [ 5 ]

6 голосов
/ 11 ноября 2008

Не можете ли вы поднять предел памяти? Похоже, лучшее решение для меня.

Редактировать: Очевидно, что увеличение лимита памяти только из-за того, что верхний предел скрипта должен поднять некоторые красные флаги, но мне кажется, что это законный случай - например. скрипт на самом деле производит довольно большие куски вывода. Таким образом, вы должны хранить выходные данные где-то , и память кажется лучшим выбором как по производительности, так и по соображениям удобства.

Следует также отметить, что ограничение памяти - это ограничение. Скрипты, которые не занимают много памяти, не будут потреблять больше только потому, что вы повысите лимит. Основная причина его существования заключается в том, чтобы не допустить неправильной работы скриптов и сбоя всего сервера. Это то, что важно, если у вас много любителей взлома на общем хосте (что-то, для чего PHP часто используется). Так что, если это ваш собственный сервер, или, по крайней мере, вы, как правило, знаете, что делаете, на самом деле не имеет смысла иметь низкий предел памяти.

2 голосов
/ 11 ноября 2008

Если ошибки php являются единственной причиной буферизации вывода, рассмотрите использование set_error_handler. С помощью этой функции вы можете определить собственный обратный вызов для ошибок в вашем скрипте. Используйте его, чтобы сохранить сообщения где-нибудь и распечатать их позже.

http://www.php.net/set_error_handler

2 голосов
/ 11 ноября 2008

Прежде чем что-либо делать, вы должны увеличить лимит памяти, особенно, если ваше единственное другое решение - просмотреть временный файл.

Существуют различные недостатки использования временных файлов (в основном, это медленнее), и если вам действительно нужен способ хранения буфера перед его выводом, перейдите к поиску memcached или APC-кеша . Это позволит вам сделать примерно то же самое, что и файл, за исключением того, что у вас есть быстрый доступ к ОЗУ.

Должен сказать, что в целом это ужасная идея. Если буфер в настоящее время не работает должным образом, вероятно, вы могли бы создать что-то по-другому, чтобы ваш сайт работал лучше.

1 голос
/ 19 марта 2013

Я бы порекомендовал попытаться загрузить файл поэтапно или разбить его на более мелкие части для включения. То, как вы это сделаете, будет сильно зависеть от того, что это за файл, но он позволит вам загрузить его, скажем,… 2 МБ чанками, если он не генерирует никаких ошибок, вы используете ob_flush() для отправки его перед загрузкой следующего чанка.

Например, вы упоминаете, что это шаблон PHP; Я не уверен, что именно это будет, если вы говорите о смешанном файле PHP / HTML, который при выполнении выдает результат, тогда вы можете попробовать добавить в шаблон некоторую форму блочного маркера, чтобы отделить отдельные части шаблона. , Таким образом, вам нужно только прочитать до конца текущего блока, затем вывести его и продолжить. Это становится сложнее, если у вас есть циклы или что-то подобное, но, как правило, всегда есть способ обойти это. Например, добавив PHP в ваши шаблоны, который вызывает метод / функцию в вашем основном скрипте, которая может обрабатывать циклический вывод поэтапно.

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

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

1 голос
/ 12 ноября 2008

Чтобы вы могли исчерпать память из-за выходных данных, у вас должно быть огромное количество данных или очень низкие пределы памяти. 4 года назад ограничение памяти в 8 Мб было достаточно распространенным и разумным. Но с переходом на использование объектов и просто улучшенные стили кодирования в целом использование памяти скриптами, с которыми я сталкивался, увеличилось.

Хм ... где у ваших скриптов не хватает памяти? Если это всегда в ваших функциях фильтрации вывода, может быть, их просто нужно оптимизировать? memory_get_usage () вернет объем памяти, используемый вашим сценарием на тот момент.

Какой текущий предел памяти у вас работает? Вы работаете в общей среде? На данный момент у меня есть ограничения памяти между 64 и 128 в зависимости от сервера.

Если вы хотите увеличить лимит только для определенного набора сценариев, то вы можете сделать это для каждого сценария:

ini_set('memory_limit','64M');

Если вы не хотите ограничивать скрипт, вы можете установить его на -1

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...