Я включил zlib.compression
в моем сценарии PHP.
Когда я обслуживаю небольшие объемы данных с включенной буферизацией вывода (примерно до 200 МБ), все работает отлично.
Однако, когда я пытаюсь обслуживать больше данных, я получаю ошибку HTTP 500, и PHP не регистрирует никаких ошибок для нее, хотя регистрация включена и определенно работает.
В PHP не установлены обработчики вывода (output_handler
не имеет значения).
<?php
ini_set('zlib.output_compression', 4096);
@ob_start();
header('Content-Type: application/octet-stream');
readfile('/tmp/bigfile.bin');
@ob_end_flush();
При отключенной буферизации вывода (т.е. без ob_start()
/ ob_end_flush()
) все отлично работает.
Что здесь происходит ? Как это исправить ?
(Приведенный выше код является просто примером, который показывает ошибку; мне нужна буферизация вывода по разным причинам, поэтому отключение не очень хорошо; также я бы предпочел использовать сжатие, если это возможно)
Оказывается, проблема с ограничением памяти (удаление @
перед ob_*()
функции будут выдавать сообщения об ошибках).
Использование буферизации вывода и HTTP-сжатия, очевидно, использует много памяти.
Мой предел памяти был 1024 МБ, и сценарий завершился ошибкой с файлом на 230 МБ.
Если мы предположим, что readfile()
загружает весь файл в память перед передачей в буферизацию вывода, это все равно будет readfile()
+ выходная буферизация + компрессия ~ 230 МБ + 230 МБ + 230 МБ + небольшой резерв для сжатия и буферизации ~ всего около 800 МБ, что намного ниже 1024 МБ …
Итог: не используйте сжатие и выходную буферизацию для больших данных.
Других решений пока нет …