Мне нужно обработать несколько больших файлов, скажем, по 50 МБ каждый. Я обнаружил, что функции PHP занимают большие части памяти. В приведенном ниже примере объем памяти, используемой функциями PHP, в четыре (4) раза превышает размер файла. Я могу понять временное использование в два раза больше памяти файла, но не в четыре раза. В конце концов PHP уничтожает memory_limit. Хотя я могу увеличить PHP memory_limit, это не очень хорошее долгосрочное решение, так как мне, возможно, придется обрабатывать большие файлы, а в производственной среде PHP требует 400 МБ на процесс, что нежелательно.
Код:
$buf = '';
report_memory(__LINE__);
$buf = file_get_contents('./20MB.pdf');
report_memory(__LINE__);
base64_encode($buf);
report_memory(__LINE__);
urlencode($buf);
report_memory(__LINE__);
function report_memory($line=0) {
echo 'Line: ' . str_pad($line,3) . ' ';
echo 'Mem: ' . str_pad(intval(memory_get_usage()/1024 ) . 'K',8) . ' ';
echo 'Peak: ' . str_pad(intval(memory_get_peak_usage()/1024) . 'K',8) . ' ';
echo "\n";
}
Выход:
Line: 4 Mem: 622K Peak: 627K
Line: 7 Mem: 21056K Peak: 21074K
Line: 10 Mem: 21056K Peak: 48302K
Line: 13 Mem: 21056K Peak: 82358K
Можно видеть, что для файла размером 20 МБ текущее использование памяти колеблется в 21 МБ, в то время как пиковое использование памяти возрастает до безумных 82 МБ.
Функции PHP, используемые в примере, являются произвольными, я могу легко поменять их местами в str_replace, is_string, gettype и т. Д. С теми же результатами.
Вопрос в том, как я могу удержать PHP от этого?
Среда — CentOS 6.6, работающая под управлением PHP 5.3.3.
Спасибо за понимание.
Вы URL-кодирование. Учитывая, что ваш PDF в основном «случайный» двоичный мусор, МНОГО из байтов там не для печати. Это означает, что вы переходите от однобайтового двоичного символа к 3-байтовой строке в кодировке URL. Учитывая, что у вас 20-миллиметровый PDF-файл, неудивительно, что троекратное количество текста в нем увеличит вашу память. Помните, что PHP должен хранить ДВУХ копий вашего PDF, пока он работает: исходную «сырую» версию и рабочую копию любого преобразования, которое вы делаете с ним.
Предполагая наихудший случай «каждый отдельный символ кодируется», ваш 20-миллиметровый PDF-файл преобразуется в строку с 60-миллиметровым URL-кодом, вызывая пиковое использование 20 + 60 = 80 мегабайт, даже несмотря на то, что эта закодированная 60-миллиметровая версия немедленно отбрасывается.
Других решений пока нет …