2012-04-02 17 views
4

많은 사람들이있는 PHP 스크립트를 SOAP을 통해 외부 리소스에서 가져 와서 수정 한 다음 다시 보냅니다. 세부 사항의 크기 때문에 나는 PHP의 메모리를 128MB로 올렸습니다. 약 4 시간 정도 달리면 (실행하는 데 4 일이 걸릴 것입니다) 메모리가 부족합니다. 그것이 무엇을의 Heres는 기초 : 그것은 메모리가 부족하고 추락가비지 컬렉터는 PHP에서 어떻게 작동합니까?

$people = getPeople(); 
foreach ($people as $person) { 
    $data = get_personal_data(); 
    if ($data == "blah") { 
     importToPerson("blah", $person); 
    } else { 
     importToPerson("else", $person); 
    } 
} 

후 나는 데이터 foreach 루프 전에 $를 초기화하기로 결정하고 top에 따라, 프로세스에 대한 메모리 사용량은 7.8 % 이상 상승하지 않은 12 시간 동안 뛰었 어.

내 질문은, 다시 사용할 경우에도 루프 안에 초기화 된 변수에 가비지 수집기가 실행되지 않는 것입니까? 시스템이 메모리를 회수하고 있으며 PHP가 아직 그것을 사용할 수있는 것으로 표시하지 않았고 결국 다시 충돌 할 것입니다 (이제는 256MB로 올렸으므로 2 가지를 수정 했으므로 확실하지 않습니다. 스크립트를 사용하면 답변을 얻을 수 있지만 나중에 12 시간 동안 기다려서 계산하지 못할 수도 있습니다.)

저는 Zend 프레임 워크를 사용하지 않으므로 다른 질문은 적합하지 않다고 생각합니다.

편집 : 실제로 스크립트 나 그 일에 어떤 문제가 없습니다. 현재 모든 시스템보고가 관련되어있는 한 어떤 문제도 없습니다. 이 질문은 가비지 수집기 및 foreach 루프에서 리소스를 회수하는 방법 및/또는 시스템에서 PHP 프로세스의 메모리 사용량을보고하는 방법에 대한 것입니다.

+2

저는 왜 두 번 투표가 내려 졌는지 듣고 싶습니다. – Moses

+0

'importToPerson()'은 어떻게됩니까? – PeeHaa

+1

if ($ data == "blah") {'? ($ data = "blah") {if? – PeeHaa

답변

0

memory_get_usage()을 사용하여 진행 상황을 확인 하시겠습니까? 루프의 내부에 배치하여 메모리 할당의 동작을 볼 수 있습니다. 시스템 모니터 나 그 과정에서 PHP가 사용하고있는 메모리 양을 확인해 보았습니까?

+0

스크립트 atm을 처음부터 다시 시작해야하므로 (이미 하루가 지나면) 스크립트를 수정하고 싶지는 않습니다. Top은 시스템 모니터이며 메모리 사용량이 7.8 %를 넘지 않아 이론적으로 더 이상 메모리 할당과 스크립트에 메모리가 부족하지 않아야합니다. – Rudiger

+0

그리고 반복 수에 제한이있는 이러한 수정으로 다른 스크립트를 실행할 수 없습니까? 즉, 내가하는 일을 완전히 확신하지 못합니다. – Norm

+0

스크립트는 많은 SOAP 요청/데이터베이스 조작을 수행하기 때문에 실제 프로세스 집중적입니다. 답을 얻을 수 없다면 조금 후에 조사하겠습니다 만 스크립트를 변경하고 1 시간 정도 실행하여 메모리 할당을 모니터링하고 헹구고 반복하는 하루가 걸릴 것입니다. 좀 더 통찰력을주기 위해 PHP 가비지 컬렉터에서 나 자신보다 knowledgable 한 누군가를 기대하고 있었다. – Rudiger

2

PHP의 VM 내부를 모르지만 내 경험에 의하면 페이지가 실행되는 동안 가비지 수집되지 않습니다. 이는 페이지 작성이 완료 될 때 페이지를 모두 버리게하기 때문입니다.

대부분의 경우 페이지 메모리가 부족하여 한계가 꽤 높고 128MB가 높지 않은 경우 알고리즘 문제가 있습니다. 많은 PHP 프로그래머가 데이터 구조를 어셈블 한 다음 구조를 반복하는 다음 단계로 전달하여 대개 다른 구조를 만듭니다. 비누로 씻고, 반복하십시오. 불행히도,이 방법은 큰 메모리를 필요로하고 메모리에 여러 개의 데이터 복사본을 생성하게됩니다. PHP 5의 두 가지 큰 변화 중 하나는 객체가 참조 횟수가 계산되고 복사되지 않으며 전체 문자열 하위 시스템이 훨씬 빠르게 작성된다는 것입니다. 하지만 여전히 문제입니다.

메모리 사용을 최소화하려면 알고리즘을 다시 구성하여 처음부터 끝까지 한 조각의 데이터로 작업 할 수 있습니다. 다음 당신은 다음을 얻고 다시 시작합니다. 가장 좋은 경우는 전체 데이터 세트를 메모리에 저장하지 않아도된다는 것입니다. 데이터베이스 기반 웹 사이트의 경우, 이것은 데이터베이스 쿼리의 데이터 행을 프레젠테이션까지 처리하여 다음 데이터를 가져 오는 것을 의미합니다. 물론이 접근법은 항상 가능하지는 않으며 스크립트는 방대한 양의 데이터를 메모리에 보관해야합니다.

즉, 데이터의 일부에 대해 이러한 메모리 절약 방식을 사용할 수 있습니다. 트릭은 명시 적으로 unset() 키 변수 또는 루프 끝의 두 변수입니다. 이 공간을 재생해야합니다. 다른 "모범 사례"트릭은 루프에있을 필요가없는 루프 데이터 조작에서 벗어나는 것입니다. 당신이 발견 한 것처럼 보입니다.

1Gb 이상의 메모리가 필요한 PHP 스크립트를 실행했습니다.스크립트 당 메모리 한도를 실제로 설정할 수 있습니다. ini_set('memory_limit', '1G');

+2

PHP 5.3에서 "실제"가비지 수집기가 추가되었습니다. 그것은 여전히 ​​불완전하지만, 당신이 묘사하고있는 것보다 개선 된 것입니다. – duskwuff

+0

실제로 명령 줄에서 실행 중입니다. 모든 행보다는 모든 행을 수행하고 반환 된 배열을 반복하는 것으로 생각했지만 필자는 여분의 데이터베이스 쿼리로 인해 모든 이점을 무효화 할 수 있다고 생각했습니다. – Rudiger

+1

각 행을 처리하는 데 엄청난 루프가 발생하는 것은 당연한 일이지만, 이전 쿼리의 결과를 가져 오는 중일 때 새 쿼리를 실행하는 데 리소스 문제가 발생할 수 있습니다. 또한 때로는 더 적은 수의 무거운 SQL 쿼리보다 많은 작은 SQL 쿼리를 수행하는 것이 더 빠릅니다. – staticsan

관련 문제