PHP буферизация буферизация вывода в PHP


Содержание

Зачем использовать буферизацию вывода в PHP?

Я прочитал довольно много материала в Интернете, где разные авторы предлагают использовать буферизацию вывода. Самое смешное, что большинство авторов аргументируют его использование только потому, что оно позволяет смешивать заголовки ответов с реальным содержимым. Честно говоря, я думаю, что ответственные веб-приложения не должны смешивать выходные заголовки и контент, и веб-разработчики должны искать возможные логические недостатки в своих сценариях, которые приводят к отправке заголовков после генерации вывода. Это мой первый аргумент против ob_* API буферизации вывода. Даже для такого небольшого удобства, которое вы получаете — смешивая заголовки с выводом, — это недостаточно веская причина для его использования, если только вам не нужно быстро взламывать сценарии, что обычно не является ни целью, ни способом серьезного веб-приложения.

Кроме того, я думаю, что большинство людей, имеющих дело с API буферизации вывода, не думают о том факте, что даже без явной буферизации вывода PHP в сочетании с веб-сервером, к которому он подключен, все равно выполняет некоторую внутреннюю буферизацию. Это легко проверить — сделайте эхо какой-нибудь короткой строки, поспите, скажем, 10 секунд, и сделайте другое эхо. Запросите ваш скрипт в браузере и наблюдайте за паузой пустой страницы в течение 10 секунд, после чего появятся обе строки. Прежде чем некоторые скажут, что это артефакт рендеринга, а не трафик, отслеживание фактического трафика между клиентом и сервером показывает, что сервер сгенерировал Content-Length заголовок с соответствующим значением для всего вывода — предполагая, что вывод не был отправлен последовательно с каждым echo вызов, но накапливается в некотором буфере, а затем отправляется при завершении сценария Это одна из моих проблем с явной буферизацией вывода — зачем нам две разные реализации буфера вывода друг на друга? Может ли это быть из-за того, что внутренняя (недоступная) буферизация вывода PHP/Web-сервера зависит от условий, которые разработчик PHP не может контролировать, и, таким образом, на самом деле не может использоваться?

В любом случае, я, например, начинаю думать, что следует избегать явной буферизации вывода (серия ob_* функции) и полагаться на неявное, помогая ему с хорошим flush функция, когда это необходимо. Может быть, если бы была какая-то гарантия от веб-сервера на фактическую отправку вывода клиенту при каждом вызове echo / print, тогда было бы полезно установить явную буферизацию — ведь никто не хочет отправлять ответ клиенту с некоторыми 100 байтовые куски. Но альтернатива с двумя буферами кажется несколько бесполезным уровнем абстракции.

Итак, в конечном счете, нужны ли серьезным веб-приложениям буферизацию вывода?

11 ответов

Серьезные веб-приложения нуждаются в буферизации вывода в одной конкретной ситуации:

Ваше приложение хочет контролировать то, что выводится каким-либо сторонним кодом, но нет API для управления тем, что этот код испускает.

В этом случае вы можете позвонить ob_start() непосредственно перед передачей управления этому коду, возитесь с тем, что написано (в идеале с обратным вызовом или проверкой содержимого буфера, если необходимо), а затем вызывайте ob_flush() ,

В конечном счете, PHP- функции ob_ представляют собой механизм для захвата того, что делает какой-то другой фрагмент кода, в буфер, с которым вы можете связываться.

Если вам не нужно проверять или изменять то, что записано в буфер, ничего не получится с помощью ob_start() ,

Вполне вероятно, что ваше «серьезное приложение» на самом деле является своего рода фреймворком.

В любом случае, у вас уже есть выходная буферизация

Вам не нужно ob_start() для того, чтобы использовать буферизацию вывода. Ваш веб-сервер уже буферизирует ваш вывод.

С помощью ob_start() не улучшит буферизацию вывода — фактически он может увеличить использование памяти вашего приложения и задержку за счет «накопления» данных, которые в противном случае веб-сервер уже отправил бы клиенту.

Может быть ob_start() .

. для удобства при промывке

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

В более редких случаях вы захотите скрыть данные с веб-сервера, пока у вас не будет достаточно данных для отправки. Нет смысла мешать клиенту половиной новостей, особенно если остальные станут доступными. Просто ob_start позже заключенный ob_end_flush() действительно может быть самой простой и подходящей вещью.

. если вы несете ответственность за определенные заголовки

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

Тем не менее, даже здесь, если вы не можете сделать что-то лучше, чем получить заголовок путем проверки полного выходного буфера, вы можете также позволить веб-серверу сделать это (если так будет). Код веб-сервера написан, протестирован и скомпилирован — вряд ли вы улучшите его.

Например, было бы полезно установить Content-Length заголовок, если ваше приложение знает длину тела ответа после того, как оно вычисляет тело ответа.

Нет панацеи от плохой практики

Вы не должны ob_start() избегать дисциплин:

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

Если вы сделаете это, они вызовут технический долг, который однажды заставит вас плакать.

Буферизация вывода в PHP?

December 2020

3.6k раз

Я, кажется, запутался вывод PHP буферизации. У меня есть такой код:

Но это, кажется, не нравится ob_get_clean (). Я делаю это потому, что некоторые HTML могут случайно получить сгенерированные, прежде чем он попадет в тот момент, но я думал, что это было то, как вы должны были сделать это.

Что мне не хватает?

6 ответы

вы должны сделать ob_start, прежде всего кода, чтобы поймать любой вывод до того, что функция вызывается

Используйте ob_get_level() функцию , чтобы увидеть , если выходной буфер активен , и выйти из него:

Если вы просто хотите, чтобы очистить буфер после начала буферизации вывода с

Также имейте в виду, что ничего не уже промыт функции, такие как эхо, print_r и т.д. Таким образом, первое, что в сценарии должны быть ob_start (). Убедитесь, что ваш включает сделать уже не отправить что-то в браузере.

Для того, чтобы использовать ob_get_clean (), вы должны быть уверены, что в какой-то момент вы ob_start () ‘ред ранее. В противном случае, нет никакого буфера для очистки, все уже выгружен на агент пользователя.

Если проблема у Вас есть то, что ничто не собирается выводить, вы, кажется, отсутствует промывочный метод? Кроме того, ob_end_clean () может быть вызван только после начала буферизации вывода, в противном случае она возвращает «ложь». Вы не можете использовать ob_ методы, чтобы очистить любые существующие заголовки, которые уже были выпущены, вы должны убедиться, что вы сами.

ob_start должна вызываться перед созданием любого контента. Обычное использование было бы что-то вроде:


Как отключить буферизацию вывода в PHP

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

Проблема заключается в PHP, как представляется, буферные эти данные. Когда я установил камеру на 1 FPS, подача замерзнет в течение 7-8 секунд, а затем быстро отображать 8 кадров. Если установить разрешение на огромный размер, перемещать камеру на более или менее 1 кадр в секунду. Я предполагаю, что тогда некоторые буферизация происходит (так как огромные размеры заполнения буфера быстро, и низкие размеры не делают), и я не могу понять, как отключить эту буферизацию. Кто-нибудь знает, как?

ТЛ; др версия

Отключение выходного буфера в пользовательском пространстве, либо .

Во всем мире, либо .

    Выключение output_buffering в вашем php.ini, или
Илон Маск рекомендует:  Что такое код globalunfix

Выключение output_buffering в вашей Apache конфигурации с помощью

или просто сценарий, вы заботитесь о, либо .

  • вызова ob_end_flush() или
  • призвание ob_end_clean()

Кроме того, отключение выходного буфера на уровне сервера, насколько это возможно, либо:

  • вызывая ob_implicit_flush() в начале вашего скрипта, или
  • вызова flush() после каждого echo заявления или другого заявления , которое добавляет вывод в тело ответа

дольше версия

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

Выходной буфер

Первый слой, как правило , ссылаются на PHP документах как «» выходного буфера. Этот слой буферизации влияет только на выход к телу ответа HTTP, а не заголовки. Вы можете включить буферизацию вывода с ob_start() , и выключить его ob_end_flush() или ob_end_clean() . Вы также можете иметь все ваши скрипты автоматически начинаются с буферизацией вывода об использовании output_buffering опции в php.ini.

Значение по умолчанию этой опции для производства версий php.ini 4096, что означает , что первые 4096 байт выхода будут буферные в выходном буфере, после чего она будет очищена и буферизация вывода выключена.

Вы можете отключить этот слой буферизации глобально, установив output_buffering для Off в файле php.ini (или с помощью

в вашей Apache конфигурации, если вы используете Apache). Кроме того , вы можете отключить его для одного сценария по телефону ob_end_clean() или ob_end_flush() в начале сценария.

Буфер записи, а буфер веб-сервер

Помимо выходного буфера является то , что PHP руководство относится к как «буфер запись», плюс буферная система ваш веб — сервер имеет. Если вы используете PHP с Apache через mod_php , и не используется mod_gzip , вы можете позвонить , flush() чтобы смыть их; с другими движками, он может работать также, хотя руководство скрытное о предоставлении гарантии:

Описание

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

Flush () не может быть в состоянии перекрыть схему буферизации вашего веба — сервер , и это не имеет никакого эффекта на любой сторону клиента буферизации в браузере. Он также не влияет на механизм буферизации вывода в пользовательском пространстве РНР. Это означает , что вы должны будете звонить как ob_flush () и флеш () для очистки выходных буферов О.Б. , если вы используете их.

Есть также несколько способов , которые вы можете сделать PHP автоматически вызывать flush() каждый раз , когда вы echo что — нибудь (или сделать что — нибудь еще , что перекликается выход к телу ответа).

Первый заключается в вызове ob_implicit_flush() . Обратите внимание , что эта функция обманчиво имени; учитывая его ob_ префикс, любой разумный человек будет ожидать , что это будет влиять на «выходной буфер», как это делают ob_start , и ob_flush т.д. Тем не менее, это не так; ob_implicit_flush() , Как flush() , влияет на выходной буфер уровня сервера и не взаимодействует каким — либо образом с выходным буфером под контролем других ob_ функций.

PHP буферизация: буферизация вывода в PHP

Что может огорчать посетителя Вашей страницы? Конечно, многое :). Но не на последнем месте стоит скорость и плавность загрузки. Поэтому поговорим о буферизации вывода и сжатии страниц в PHP.

Начнем с обычной буферизации. Для начала нам нужно это дело включить (делается перед всеми выводами, иначе смысл этого действия пропадает):

Теперь все, что выводит наш скрипт, будет попадать не прямиком юзеру, а в буфер. Конечно, в конце скрипта надо пользователю показать все выведенное:

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

Теперь перейдем к сжатию. По сути, это вЂ‛ логическое продолжение буферизации вывода. Только теперь мы будем архивировать то, что посылается пользователю. Таким образом, мы заметно сэкономим трафик.

Нужно учитывать, что не все браузеры поддерживают принятие сжатого контента. Кроме того, необходимо, чтобы на сервере при компиляции PHP был подключен zlib. Поэтому перед основной работой проверим, можем ли мы использовать блага архивации:

Теперь смело включаем уже знакомую нам буферизация:

Можно еще добавить запрет на вывод буфера без нашего на то указания:

Но это не очень хорошая идея, поскольку если у нас где-то до полноценного вывода данных встретится, например, вызов die(), то юзер не увидит ничего, что выводилось до этого.


Ну а в конце выводим данные несколько другим способом:

Все просто, не правда ли? Проверяем, можно ли использовать сжатие. Если да вЂ‛ выдаем корректный header и сжатый контент. Если нет вЂ‛ ничего не сжимаем.

Есть и второй путь. Можно все это проделать одной строкой:

О дальнейшем выводе можно не думать. Но у такого подхода есть существенный минус. При использовании mod_rewrite будет выдаваться ошибка. И данные сжиматься не будут. У предыдущего подхода такого недостатка нет.

Прочтение данной статьи не освобождает от прочтения документации, ибо в с статье не описаны многие нюансы происходящего.

Что такое буферизация вывода?

Что такое буферизация вывода и почему она используется в PHP?

7 ответов

Без буферизации вывода (по умолчанию) ваш HTML отправляется в браузер частями как PHP-процессы через ваш скрипт. При буферизации вывода HTML сохраняется в переменной и отправляется в браузер как единое целое в конце скрипта.

Преимущества буферизации вывода для веб-разработчиков

  • Включение только буферизации вывода уменьшает время, необходимое для загрузки и визуализации нашего HTML, потому что он не отправляется в браузер частями, как PHP обрабатывает HTML.
  • Все необычные вещи, которые мы можем сделать со строками PHP, теперь мы можем сделать со всей нашей HTML-страницей в качестве одной переменной.
  • Если вы когда — либо сталкивались с сообщением «Warning: Cannot modify header information-headers already sent by (output)» при настройке файлов cookie, вы будете рады узнать, что буферизация вывода является вашим ответом.

Функции управления выходом позволяют вам
управление отправкой выходных данных
сценарий. Это может быть полезно в
несколько различных ситуаций,
особенно если вам нужно отправить заголовки
в браузер после того, как скрипт
начали выводить данные. выход
Функции управления не влияют
заголовки, отправленные с помощью header () или
setcookie (), только такие функции, как
echo() и данные между блоками PHP
код.

дополнительные ресурсы:

Буферизация вывода используется PHP для повышения производительности и выполнения нескольких трюков.

PHP может хранить все выходные данные в буфере и выводить их все сразу, улучшая производительность сети.

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

Рассмотрим этот пример:

В приведенном выше примере выходные данные записываются в переменную, а не отправляются в браузер. output_buffering выключен по умолчанию.

  • Буферизацию вывода можно использовать в ситуациях, когда требуется изменить заголовки после отправки содержимого.

Рассмотрим этот пример:

As name suggest here Memory buffer used to manage how the output of script appears.

Вот один очень хороший учебник по этой теме

Буферы могут быть вложенными, поэтому, пока один буфер активен, другой ob_start() активирует новый буфер. Таким образом, ob_end_flush() и ob_flush() на самом деле отправляют буфер не на выход, а на родительский буфер. И только когда нет родительского буфера, содержимое отправляется в браузер или терминал.

Я знаю, что это старый вопрос, но я хотел написать свой ответ для визуальных учащихся. Я не мог найти никаких диаграмм, объясняющих буферизацию вывода во всемирной паутине, поэтому я сделал что-то сам в mspaint.

Если буферизация вывода отключена, то echo данные будут отправляться немедленно в браузер.

Если буферизация вывода включена, то echo перед отправкой данных в браузер данные будут отправляться в буфер вывода.

phpinfo

Чтобы узнать, включена или выключена буферизация вывода, обратитесь к phpinfo в разделе core. output_buffering Директива сообщит вам, включена или выключена буферизация вывода.

В этом случае output_buffering значение равно 4096, что означает, что размер буфера составляет 4 КБ. Это также означает, что буферизация вывода включена на веб-сервере.

РНР.ini

Можно включить / выключить и изменить размер буфера, изменив значение output_buffering директивы. Просто найдите его php.ini , измените его на настройки по вашему выбору и перезапустите веб-сервер. Вы можете найти образец моего php.ini ниже.

Директива output_buffering не является единственной настраиваемой директивой относительно буферизации вывода. Вы можете найти другие настраиваемые директивы буферизации вывода здесь: http://php.net/manual/en/outcontrol.configuration.php

Пример: ob_get_clean()

Ниже вы можете увидеть, как захватить echo и управлять им перед отправкой его в браузер.

Примеры: Hackingwithphp.com

Подробнее о выходном буфере с примерами можно найти здесь:

Обновление 2020. Если у вас есть выделенный сервер и SSD или лучше NVM, 3,5 ГГц. Вы не должны использовать буферизацию, чтобы сделать быстрее загруженный сайт в 100ms-150ms.

Becouse сеть медленно, чем proccesing сценарий в 2020 году с производительностью серверов (Северс,памяти,диска) и с включите APC PHP �� для сгенерированного сценария иногда нужно только 70ms другое время только сеть занимает время, от 10ms до 150ms от расположенного пользователя-сервера.

Илон Маск рекомендует:  Asp компонент page counter

так если вы хотите быть быстрыми 150ms, то буферность делает slowl, becouse данные по буфера собрания потребности экстренные оно делает дополнительную цену. 10 лет назад, когда сервер делал 1S скрипт, он был полезен.


Пожалуйста, becareful output_buffering имеют предел, если вы хотите использовать jpg для загрузки он может смыть автоматизировать и аварийной отправки.

Вы можете сделать быструю реку
или
Вы можете сделать безопасно tama ��

Как отключить буферизацию вывода в PHP

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

Проблема в том, что PHP, похоже, буферизует эти данные. Когда я установлю камеру на 1 FPS, подача будет зависать на 7-8 секунд, а затем быстро отображать 8 кадров. Если я установлю разрешение огромного размера, камера будет двигаться с более или менее 1 кадром в секунду. Я предполагаю, что тогда происходит некоторая буферизация (поскольку большие размеры быстро заполняют буфер, а малые — нет), и я не могу понять, как отключить эту буферизацию. Кто-нибудь знает как?

5 ответов

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

tL; Dr версия

Сделать две вещи:

Отключите буфер вывода пользовательского пространства, либо.

Во всем мире, либо.

    Выключение output_buffering в вашем php.ini, или

Выключение output_buffering в вашем конфиге Apache, используя

или только для сценария, который вас интересует, либо.

  • призвание ob_end_flush() , или же
  • призвание ob_end_clean()

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

  • призвание ob_implicit_flush() в начале вашего сценария, или
  • призвание flush() после каждого echo оператор или другой оператор, который добавляет вывод в тело ответа

Более длинная версия

Смеется, что существует два уровня буферизации, которые могут иметь значение, и документация PHP плохо разбирает их.

Выходной буфер

Первый уровень обычно упоминается в документации PHP как «буфер вывода». Этот уровень буферизации влияет только на вывод тела HTTP-ответа, а не на заголовки. Вы можете включить выходную буферизацию с помощью ob_start() , и выключите его ob_end_flush() или же ob_end_clean() . Вы также можете автоматически запускать все ваши сценарии с буферизацией вывода при использовании output_buffering опция в php.ini.

Значение по умолчанию этой опции для производственные версии php.ini равно 4096, что означает, что первые 4096 байтов вывода будут буферизованы в буфере вывода, после чего он будет сброшен и буферизация вывода отключена.

Вы можете отключить этот уровень буферизации глобально, установив output_buffering в Off в вашем файле php.ini (или используя

в вашей конфигурации Apache, если вы используете Apache). Кроме того, вы можете отключить его для одного скрипта, вызвав ob_end_clean() или же ob_end_flush() в начале сценария.

Буфер записи и буфер веб-сервера

Помимо выходного буфера есть то, что в руководстве по PHP называется «буфер записи», плюс любая система буферизации, которую имеет ваш веб-сервер. Если вы используете PHP с Apache через mod_php , и не используют mod_gzip , ты можешь позвонить flush() очистить их; с другими бэкэндами это тоже может сработать, хотя в руководстве нет ничего общего с предоставлением гарантий:

Описание

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

flush() может не иметь возможности переопределить схему буферизации вашего веб-сервера, и это не влияет на буферизацию на стороне клиента в браузере. Это также не влияет на механизм буферизации вывода пользовательского пространства PHP. Это означает, что вам придется позвонить обоим ob_flush() и flush() для очистки выходных буферов ob, если вы их используете.

Есть также несколько способов заставить PHP автоматически вызывать flush() каждый раз, когда ты echo что-нибудь (или сделать что-нибудь еще, что отражает вывод в теле ответа).

Во-первых, позвонить ob_implicit_flush() . Обратите внимание, что эта функция обманчиво названа; учитывая его ob_ префикс, любой разумный человек будет ожидать, что это повлияет на «выходной буфер», так же как и ob_start , ob_flush и т. д. Однако это не так; ob_implicit_flush() , лайк flush() , влияет на выходной буфер уровня сервера и никак не взаимодействует с выходным буфером, управляемым другим ob_ функции.

Во-вторых, глобально включить неявную очистку, установив implicit_flush флаг для On в вашем php.ini. Это эквивалентно звонку ob_implicit_flush() в начале каждого сценария. Обратите внимание, что руководство не советует этого, загадочно ссылаясь на «серьезные последствия для производительности», некоторые из которых я исследую в этом касательно связанный ответ.

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

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

Мы можем дать приведенный ниже код в файле .htaccess для отключения буферизации вывода в PHP

Я знаю, что этот вопрос немного устарел, но возвращаясь к этому вопросу, вы можете отключить буферизацию вывода от сценария к сценарию, например так:


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

Отключение буферизации вывода в PHP

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

Я прочитал через http://www.php.net/flush и попробовал все предложения там. Очевидно, я попытался отключить output_buffering в php.ini. Я отключил deflate_module, сжатие zlib выключено, не имеет mod_gzip. Вызов flush () или ob_flush () не имеет никакого эффекта и не позволяет implicit_flush.

Я просто запускаю XAMPP (в настоящее время apache 2.2.17, php 5.3.4) под Windows Server 2008 R2. PHP запускается как модуль.

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

Из аналогичной темы кто-то предложил посмотреть, что будет делать следующее:

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

Это стало очень неприятно. У кого-нибудь есть идеи, которые все еще могут вызвать его буферизацию?

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

Короче говоря, вы ничего не можете с этим поделать. Буферизация происходит на стороне клиента, а не на стороне сервера. Вы можете попробовать отправить больше данных до вашего x s.

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

hmmm, интересно схватил fragment кода, который я использовал еще там, где он работает, как и ожидалось …

Буферизация вывода на PHP

Часто бывают случаи, когда в некотором месте программы необходимо отправить заголовки, например, для перезагрузки страницы, а контент на вывод уже отправлен или контент, который выводится раньше определенной информации, необходимо вывести после этой информации. В этом случае нужно переписывать программу, возможно, менять алгоритм, что бы добиться того, что нужно. Но можно поступить проще, для этого в PHP (скажем прямо не только для этого) и придумали замечательный набор функций начинающихся c префикса ob_ , такие как ob_start(), ob_get_contents(), ob_end_clean() и другие.

Рассмотрим на примере буферизацию вывода на PHP:

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

На следующем примере видно, как вывести контент, который выводится раньше опреленной информации, после этой информации.

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

Как отключить буферизацию вывода в PHP

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

проблема в том, что PHP, похоже, буферизует эти данные. Когда я установлю камеру на 1 FPS, подача замерзнет на 7-8 секунд, а затем быстро отобразит 8 кадров. Если я установлю разрешение на огромный размер, камера будет двигаться со скоростью более или менее 1 кадр в секунду. Я предполагаю, что происходит некоторая буферизация (поскольку огромные размеры быстро заполняют буфер, а низкие размеры-нет), и я не могу понять, как отключить эту буферизацию. Кто-нибудь знает как?

5 ответов

tl; dr version

сделать две вещи:

отключите выходной буфер пользовательского пространства.

    выключить output_buffering в вашем php.Ини, или

выключить output_buffering в конфигурации Apache с помощью

или только для сценария, о котором вы заботитесь, любой.

Илон Маск рекомендует:  Что такое код getmaxcolor

кроме того, отключите выходной буфер уровня сервера столько, сколько сможете, либо:

  • вызов ob_implicit_flush() в начале вашего скрипта, или
  • вызов flush() после echo оператор или другой оператор, который добавляет вывод в ответ тело

версия

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

выходной буфер

первый слой обычно упоминается в документах PHP как «выходной буфер». Этот уровень буферизации влияет только на вывод в тело ответа HTTP, а не заголовков. Вы можете включить буферизация вывода с помощью ob_start() , и выключите его с ob_end_flush() или ob_end_clean() . Вы также можете автоматически запускать все ваши скрипты с буферизацией вывода при использовании output_buffering опция в php.ini.

значение по умолчанию этой опции для производственные версии php.ini равно 4096, что означает, что первые 4096 байт вывода будут буферизованы в выходном буфере, и в этот момент он будет покраснел и буферизация вывода выключено.

вы можете отключить этот уровень буферизации глобально, установив output_buffering to Off в вашем php.ini-файл (или с помощью


в конфигурации Apache, если вы используете Apache). Кроме того, вы можете отключить его для одного скрипта, вызвав ob_end_clean() или ob_end_flush() в начале скрипта.

буфер записи и буфер веб-сервера

за пределами выходного буфера находится руководство PHP относится к «буферу записи», а также к любой системе буферизации вашего веб-сервера. Если вы используете PHP с Apache через mod_php , а не с помощью mod_gzip можно назвать flush() чтобы смыть их; с другими бэкэндами это тоже может сработать, хотя руководство уклончиво дает гарантии:

описание

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

flush () возможно, не удастся переопределить схему буферизации вашего веб-сервера, и это не влияет на буферизацию на стороне клиента в браузере. Это также не влияет на механизм буферизации вывода пользовательского пространства PHP. Это означает, что вам придется назвать как помощью ob_flush() и flush () для очистки выходных буферов ob, если вы используете те.

есть также несколько способов, которыми вы можете сделать PHP автоматически вызывать flush() каждый раз, когда вы echo что-нибудь (или сделайте что-нибудь еще, что Эхо выводит в тело ответа).

первое-позвонить ob_implicit_flush() . Обратите внимание, что эта функция обманчиво названа; учитывая ее ob_ префикс, любой разумный человек ожидал бы, что это повлияет на «выходной буфер», как и ob_start , ob_flush etc. Однако это не так.; ob_implicit_flush() , как flush() , влияет на выходной буфер уровня сервера и никак не взаимодействует с выходным буфером, управляемым другим ob_ функции.

второй-глобально включить неявную промывку, установив implicit_flush флаг On в вашем php.ini. Это эквивалентно вызову ob_implicit_flush() в начале каждого скрипта. Обратите внимание, что руководство советует против этого, загадочно цитируя «серьезные последствия для производительности», некоторые из которых я исследую в этом тангенциально связанный ответ.

вместо отключения буферизации вывода вы можете просто вызвать flush() после каждой операции чтения. Это позволяет избежать возни с конфигурацией сервера и делает ваш скрипт более портируемым.

буферизация вывода может быть многоуровневой, и у меня были случаи, когда более ранний код сделал несколько уровней. Это очистит их всех.

мы можем дать приведенный ниже код в.файл htaccess для отключения буферизации вывода в PHP

Я знаю, что этот вопрос немного устарел, но, возвращаясь к этому вопросу, вы можете отключить буферизацию вывода на основе сценария к сценарию, например:

Это должно выключить буферизацию вывода для любого сценария, который следует за ним.

Зачем использовать буферизацию вывода в PHP?

Я прочитал довольно много материала в Интернете, где разные авторы предлагают использовать буферизацию вывода. Самое смешное, что большинство авторов аргументируют его использование только потому, что оно позволяет смешивать заголовки ответов с реальным содержимым. Честно говоря, я думаю, что ответственные веб-приложения не должны смешивать выходные заголовки и контент, и веб-разработчики должны искать возможные логические недостатки в своих сценариях, которые приводят к отправке заголовков после генерации вывода. Это мой первый аргумент против ob_* API буферизации вывода. Даже для такого небольшого удобства, которое вы получаете — смешивая заголовки с выводом, — это недостаточно веская причина для его использования, если только вам не нужно быстро взламывать сценарии, что обычно не является ни целью, ни способом серьезного веб-приложения.

Кроме того, я думаю, что большинство людей, имеющих дело с API буферизации вывода, не думают о том факте, что даже без явной буферизации вывода PHP в сочетании с веб-сервером, к которому он подключен, все равно выполняет некоторую внутреннюю буферизацию. Это легко проверить — сделайте эхо какой-нибудь короткой строки, поспите, скажем, 10 секунд, и сделайте другое эхо. Запросите ваш скрипт в браузере и наблюдайте за паузой пустой страницы в течение 10 секунд, после чего появятся обе строки. Прежде чем некоторые скажут, что это артефакт рендеринга, а не трафик, отслеживание фактического трафика между клиентом и сервером показывает, что сервер сгенерировал Content-Length заголовок с соответствующим значением для всего вывода — предполагая, что вывод не был отправлен последовательно с каждым echo вызов, но накапливается в некотором буфере, а затем отправляется при завершении сценария Это одна из моих проблем с явной буферизацией вывода — зачем нам две разные реализации буфера вывода друг на друга? Может ли это быть из-за того, что внутренняя (недоступная) буферизация вывода PHP/Web-сервера зависит от условий, которые разработчик PHP не может контролировать, и, таким образом, на самом деле не может использоваться?

В любом случае, я, например, начинаю думать, что следует избегать явной буферизации вывода (серия ob_* функции) и полагаться на неявное, помогая ему с хорошим flush функция, когда это необходимо. Может быть, если бы была какая-то гарантия от веб-сервера на фактическую отправку вывода клиенту при каждом вызове echo / print, тогда было бы полезно установить явную буферизацию — ведь никто не хочет отправлять ответ клиенту с некоторыми 100 байтовые куски. Но альтернатива с двумя буферами кажется несколько бесполезным уровнем абстракции.

Итак, в конечном счете, нужны ли серьезным веб-приложениям буферизацию вывода?

11 ответов

Серьезные веб-приложения нуждаются в буферизации вывода в одной конкретной ситуации:

Ваше приложение хочет контролировать то, что выводится каким-либо сторонним кодом, но нет API для управления тем, что этот код испускает.

В этом случае вы можете позвонить ob_start() непосредственно перед передачей управления этому коду, возитесь с тем, что написано (в идеале с обратным вызовом или проверкой содержимого буфера, если необходимо), а затем вызывайте ob_flush() ,

В конечном счете, PHP- функции ob_ представляют собой механизм для захвата того, что делает какой-то другой фрагмент кода, в буфер, с которым вы можете связываться.

Если вам не нужно проверять или изменять то, что записано в буфер, ничего не получится с помощью ob_start() ,

Вполне вероятно, что ваше «серьезное приложение» на самом деле является своего рода фреймворком.

В любом случае, у вас уже есть выходная буферизация

Вам не нужно ob_start() для того, чтобы использовать буферизацию вывода. Ваш веб-сервер уже буферизирует ваш вывод.

С помощью ob_start() не улучшит буферизацию вывода — фактически он может увеличить использование памяти вашего приложения и задержку за счет «накопления» данных, которые в противном случае веб-сервер уже отправил бы клиенту.

Может быть ob_start() .

. для удобства при промывке

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

В более редких случаях вы захотите скрыть данные с веб-сервера, пока у вас не будет достаточно данных для отправки. Нет смысла мешать клиенту половиной новостей, особенно если остальные станут доступными. Просто ob_start позже заключенный ob_end_flush() действительно может быть самой простой и подходящей вещью.

. если вы несете ответственность за определенные заголовки

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

Тем не менее, даже здесь, если вы не можете сделать что-то лучше, чем получить заголовок путем проверки полного выходного буфера, вы можете также позволить веб-серверу сделать это (если так будет). Код веб-сервера написан, протестирован и скомпилирован — вряд ли вы улучшите его.

Например, было бы полезно установить Content-Length заголовок, если ваше приложение знает длину тела ответа после того, как оно вычисляет тело ответа.

Нет панацеи от плохой практики

Вы не должны ob_start() избегать дисциплин:

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

Если вы сделаете это, они вызовут технический долг, который однажды заставит вас плакать.

Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL