我在PHP中有一个手工制作的ORM,似乎碰到了对象限制并导致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,000MB和非常低的容量 - 24MB。如果我将它设置得足够低,我将得到“分配的内存大小xxx字节耗尽”错误。
我认为它与所调用的函数数量有关 - 某种嵌套预防。我不认为我的ORM嵌套是那么复杂但也许是这样。我有一些非常明显的案例,如果我只加载一个对象它会死掉,但如果它有效,则在3秒内加载。
答案 0 :(得分:4)
有趣的是,在我的环境中,似乎在解构对象时发生了段错误 - 在循环运行正常后放置的代码。只有在PHP开始关闭时才会发生段错误。
你可以file a bug,但是你可能会发现PHP的维护者不会竭尽全力支持这类事情。我已经看到至少一个关于内存泄漏的错误报告,其中官方响应基本上是“Wontfix:在页面呈现后释放内存,所以这并不重要” - 有效地暗示在简单之外的用途快速呈现网页并终止的情况并非真正支持。
经过5年的全职PHP开发,我已经达成了一个简单的规则:如果它崩溃了PHP,那就不要这样做了。 PHP有其局限性,如果你不推动这些限制,你会发现自己最成功。
这意味着避免PHP中的create_function()
&lt; = 5.2(它像疯了一样泄漏内存)。您可以尝试使用create_function()
来使用PHP,就像它是一种函数式语言一样。它不是,如果你试图使用它,你会发现它失败了。
因此,如果PHP在40000级深度的嵌套对象上窒息...不要将对象嵌套40000级深。一种可能的替代方案是使用数组而不是对象 - 但这仍然听起来非常令人发指。