У меня есть ORM ручной работы на PHP, который, кажется, сталкивается с ограничением объекта и вызывает сбой php. Вот простой скрипт, который вызовет сбои:
<? class Bob { protected $parent; public function Bob($parent) { $this->parent = $parent; } public function __toString() { if($this->parent) return (string) "x " . $this->parent; return "top"; } } $bobs = array(); for($i = 1; $i < 40000; $i++) { $bobs[] = new Bob($bobs[$i -1]); } ?>
Даже запуск этого из командной строки вызовет проблемы. В некоторых коробках содержится более 40 000 объектов. Я пробовал это на Linux / Apache (сбой), но мое приложение работает на IIS / FastCGI. В FastCGI это приводит к ошибке «Быстрое завершение процесса FastCGI».
Очевидно, что объекты 20k немного высоки, но сбрасываются с гораздо меньшим количеством объектов, если у них есть данные и сложная сложность.
Быстрый CGI не проблема – я попытался запустить его из командной строки. Я попытался установить память на что-то действительно высокое – 6 000 МБ и на что-то действительно низкое – 24 МБ. Если я установил его достаточно низким, я получу ошибку «освобожденный размер памяти xxx».
Я думаю, что это связано с количеством функций, которые называются – своего рода предотвращение вложенности. Я не думал, что мое гнездо ORM было таким сложным, но, возможно, так оно и есть. У меня есть довольно четкие случаи, когда я загружаю только один объект, который он умирает, но загружается менее чем за 3 секунды, если он работает.
Интересно, что в моей среде кажется, что segfault возникает, когда приходит время для деконструкции объектов – кода, помещенного после того, как цикл работает нормально. Это происходит только тогда, когда PHP начинает отключать работу segfault.
Вы можете указать ошибку , но вы можете обнаружить, что разработчики PHP не будут мешать им поддерживать подобные вещи. Я видел, по крайней мере, один отчет об ошибке утечки памяти, в котором официальный ответ был по существу «Wontfix: память выпущена после отображения страницы, поэтому это не имеет большого значения» – фактически подразумевая, что использование за пределами простого случай быстрого рендеринга веб-страницы и завершения не поддерживается.
После 5-летней разработки PHP, я пришел к простому правилу: если он сбой PHP, не делайте этого. PHP имеет свои ограничения, и вы окажетесь наиболее успешными, если не нажмете эти ограничения.
Это означает, что вы избегаете create_function()
в PHP <= 5.2 (он утешает память как сумасшедший). Вы можете попытаться использовать create_function()
для использования PHP, как если бы это был функциональный язык. Это не так, и вы обнаружите, что это терпит неудачу, если вы попытаетесь использовать его как таковой.
Поэтому, если PHP задыхается при вложенности объектов 40000 уровней в глубину … не гнездятся объекты глубиной 40000 уровней. Одной из возможных альтернатив является использование массивов вместо объектов, но это все еще звучит довольно отвратительно.