2010-03-16 1 views
2

나는 많은 양의 데이터를 클라이언트에, 아마도 오랜 기간 동안 작성해야하는 mod_perl에서 실행되는 Perl 스크립트를 가지고있다. 내가 관찰 한 동작은 일단 내가 인쇄하고 플러시를하면, 내가 rflush (나는 이것이 OS에 의해 다시 회수 될 수 없다는 것을 알고 있음)이지만 버퍼 메모리는 회수되지 않는다는 것이다.mod_perl에 버퍼 메모리를 다시 사용하도록 할 수있는 방법이 있습니까?

mod_perl이 작동하는 방식이며 버퍼 메모리를 주기적으로 해제하여 OS에서 더 많이 차지하는 대신 새 버퍼를 사용할 수있는 방법이 있습니까?

그냥 명확히하기 위해 버퍼를 직접 사용하지 않고 코드에 누수가 없습니다. 다음의 간단한 예를 생각해보십시오.

이 누수가 심하고 내 요청이 살아 있기 때문에 며칠 동안 활성화 될 수 있습니다.

+0

명확히하기 위해, 나는 버퍼를 직접 사용하지 않고 있으며 코드에 누수가 없습니다. 다음 간단한 예제를 고려하십시오. sub handler { my $request = shift; my $boundary = time; $request->content_type("multipart/x-mixed-replace;boundary=\"$boundary\";"); for (;;) { $request->print("--$boundary\n"); $request->print("Content-type: text/html; charset=utf-8;\n\n"); $request->print("$data\n\n"); $request->rflush; } return Apache2::Const::OK; } 이 누수가 많이 발생하고 요청이 활성 상태로 유지되어 며칠 동안 활성화 될 수 있습니다. –

답변

-1

버퍼에 대한 참조를 해제하십시오. 예를 들어, 문자열을 버퍼로 사용할 경우

$buf = "really long string " . "and other methods that make it huger"; 
print SOMEWHERE $buf; 
$buf = ""; # or undef $buf according to taste 

이전에 $ buf가 가리키는 저장소를 사용 가능한 풀로 반환해야합니다.

+1

빈 문자열을 할당해도 PV가 유지됩니다! 'undef' 함수 만이 이것을 제거합니다.그러나 둘 다 마지막 참조를 죽이지 않습니다. 적절한 작업은 불필요한 변수가 범위를 벗어나는 것입니다. – daxim

2

메모리를 OS로 반환하지 않는 것은 perl 인터프리터 자체의 표준 동작이며 mod_perl 자체와 관련이 없습니다. 공유 메모리 (IIRC, 수동으로 할당/할당 해제 처리)를 사용하거나 프로세스를 종료하는 것 이외에 호스트 메모리에 메모리를 해제하기 위해 perl을 다시 얻는 방법을 알지 못합니다.

변수를 범위를 벗어나게하면 perl은 다른 변수에 해당 메모리를 다시 사용할 수 있지만 OS로 반환하지는 않습니다.

편집 : 난 그냥 질문을 다시 읽고 그냥 perl하지 않는 OS에 공개하려고 메모리를 재 - 사용할 수 있도록하는 방법을 찾고 있다는 것을 깨달았다. 이 경우 어휘 (my) 변수를 사용하고 전역 버퍼를 일찍 정의하고 영원히 유지하는 대신 가능한 가장 작은 범위로 제한하는 것이 트릭을 수행해야합니다.

0

당신의 for (;;) 루프는 as-written로 끝나지 않을 수 있습니다. 이것은 메모리 누수보다 더 심각한 문제로 이어질 것입니다. print 메소드는 요청을 정리할 때 일반적으로 릴리스되는 요청 레코드의 일부로 메모리를 할당해야합니다. 이것은 mod_perl2 또는 Apache2 내에서 C 코드에서 발생합니다.

이 문제를 해결하려면 접근 방식을 다시 설계해야합니다. mod_perl 핸들러에서 장기 실행 응답을 보내는 대신, 사용자를 ProxyPass 설정을 통해 STDOUT에 대한 응답을 인쇄하는 프로그램으로 재 지정하십시오. (본질적으로 CGI 스크립트입니다.) 스크립트는 다른 포스터가 변수 범위를 제한하는 것에 대해 언급 한 기술이 작동 할 수있는 pure-perl이 될 수 있습니다. 응답은 여전히 ​​아파치를 통과하지만 리버스 프록시로 작동 할 때 아파치는 버킷 여단에 데이터를 복사하는 고정 된 버퍼 세트를 가지고있다. 역 프록시 프로세스가 방대한 양의 데이터를 거치지 만 많은 메모리를 소비한다는 것을 본 적이 없습니다.