При вызове функций и передаче большой строки я обычно передаю ссылку. Намерение состоит в том, чтобы не дать PHP передавать по значению копию строки, тем самым уменьшая использование памяти. Тем не менее, я заметил обратное при определенных обстоятельствах.
В приведенном ниже примере пиковое использование памяти удваивается при передаче строки по ссылке в функцию при вызове is_string ().
Код:
$buf = '';
report_memory(__LINE__);
$buf = file_get_contents('./20MB.pdf');
report_memory(__LINE__);
example($buf);
report_memory(__LINE__);
function example(& $str) {
report_memory(__LINE__);
is_string($str);
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: 2 Mem: 625K Peak: 631K
Line: 5 Mem: 21058K Peak: 21076K
Line: 11 Mem: 21058K Peak: 21076K
Line: 13 Mem: 21058K Peak: 41494K
Line: 8 Mem: 21058K Peak: 41494K
Изменение функции example () для удаления ссылки:
function example($str) {
report_memory(__LINE__);
is_string($str);
report_memory(__LINE__);
}
Выход:
Line: 2 Mem: 625K Peak: 631K
Line: 5 Mem: 21058K Peak: 21076K
Line: 11 Mem: 21058K Peak: 21076K
Line: 13 Mem: 21058K Peak: 21076K
Line: 8 Mem: 21058K Peak: 21076K
Это то, что я ожидал. Тогда почему память удваивается с помощью is_string (), когда переменная является ссылкой?
Среда — CentOS 6.6, работающая под управлением PHP 5.3.3.
Zend Engine использует механизм отложенного копирования. Пока переменная не изменена, она не создает копию переменной. PHP создает набор структур, которые он использует для поддержки ссылки, поэтому он на самом деле «медленнее» передает переменную по ссылке.
Других решений пока нет …