2010-04-06 3 views
1

나는 PHP에서 수제 한계를 극복하고 PHP를 일으키는 것처럼 보이는 handmade 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]); 
}  
?> 

명령 줄에서 실행하는 경우에도 문제가 발생합니다. 일부 상자는 4 만 개가 넘는 객체를 사용합니다. Linux/Apache (실패)에서 시도했지만 IIS/FastCGI에서 실행됩니다. FastCGI에서 이로 인해 유명한 "FastCGI 프로세스가 예기치 않게 종료되었습니다"라는 오류가 발생합니다.

분명히 20k 개체는 약간 높지만 데이터와 중첩 된 복잡성을 가진 개체는 훨씬 적습니다.

빠른 CGI는 문제가 아닙니다. 명령 줄에서 실행 해 보았습니다. 저는 실제로 6 천 2 백 메가 바이트의 메모리와 24 메가 바이트의 정말로 낮은 메모리를 설정하려고했습니다. 충분히 낮게 설정하면 "할당 된 메모리 크기 xxx 바이트가 소모되었습니다"오류가 발생합니다.

저는 그것이 어떤 종류의 중첩 방지라고하는 함수의 수와 관련이 있다고 생각합니다. 내 ORM의 중첩은 복잡하지만 어쩌면 그렇게 생각하지 않았습니다. 나는 분명히 하나의 더 많은 객체를로드하면 작동하지만 3 초 이내에로드하는 꽤 명확한 경우가 있습니다.

답변

4

흥미롭게도, 내 환경에서는 개체가 해체 될 때 segfault가 발생하는 것으로 나타났습니다. 루프가 정상적으로 실행 된 후에 배치 된 코드입니다. PHP가 종료 될 때만 segfault가 발생합니다.

당신은 file a bug 일 수 있지만, PHP의 관리자는 이런 종류의 일을 지원하지 않을 것입니다. 적어도 공식 응답이 "Wontfix : 메모리가 페이지가 렌더링 된 후에 릴리스되므로 실제로는 중요하지 않습니다"라는 메모리 누수에 관한 버그 리포트를 보았습니다. 웹 페이지를 빠르게 렌더링하고 종료하는 경우는 실제로 지원되지 않습니다.

5 년간의 풀 타임 PHP 개발을 마치고 난 다음과 같은 간단한 규칙에 도달했습니다. PHP가 작동을 멈추는 경우이를 수행하지 마십시오. PHP에는 한계가 있으며 이러한 한계를 넘기지 않으면 가장 성공적이라고 할 수 있습니다.

create_function()을 PHP < = 5.2 (미친 듯이 메모리가 누출 됨)로 피하는 것과 같은 의미입니다. PHP를 함수형 언어처럼 사용하려면 create_function()을 사용할 수 있습니다. 그것은 아닙니다, 그리고 당신이 그것을 비참하게 사용하려고 시도한다면 실패 할 것입니다.

그래서 개체를 중첩하는 경우 40000 단계의 PHP 초크가 발생하면 40000 단계의 개체가 중첩되지 않습니다. 한 가지 가능한 대안은 객체 대신 배열을 사용하는 것입니다.하지만 여전히 꽤 까다로운 소리입니다.

+1

"의사, 내가 * * * 할 때 아파!" "그러지 마." –