2016-11-13 4 views
2

필자가 작성한 perl 스크립트의 메모리 사용에 약간의 문제가 있습니다 (아래 코드). 스크립트는 일부 변수를 시작하고 데이터로 채운 다음 다시 정의 해제합니다. 그러나 모든 것을 삭제 한 후 스크립트의 메모리 사용량은 여전히 ​​데이터를 포함하지 않는 높은 수준입니다.메모리에서 perl 객체를 제거하는 방법

Accoke to ps 스크립트는 처음 39 초 동안 1.027 Mb 메모리 (RSS)를 사용합니다 (foreach 루프 이전의 모든 내용). 그런 다음 메모리 사용이 증가하기 시작하여 204.391 Mb와 172.410 Mb 사이에서 변동합니다. 그러나 스크립트의 마지막 10 초 (모든 데이터가 제거되어야하는 곳)에서도 메모리 사용량은 172.410MB 이하로 떨어지지 않습니다.

스크립트의 메모리 사용을 줄이기 위해 perl에서 변수와 모든 데이터를 영구적으로 삭제하는 방법이 있습니까? 그렇다면 어떻게해야합니까?

use strict; 
use warnings; 

sleep(30); 

my $ELEMENTS = 1_000_000; 
my $MAX_ELEMENT = 1_000_000_000; 
my $if_condition = 1; 

sleep(5); 

my %hash = (1 => {}, 2 => {}, 3 => {}, 4 => {}); 

foreach my $key (keys %hash){ 
    if($if_condition){ 
     my $arrref1 = [ (rand($MAX_ELEMENT)) x $ELEMENTS ]; 
     my $arrref2 = [ (rand($MAX_ELEMENT)) x $ELEMENTS ]; 
     my $arrref3 = [ (rand($MAX_ELEMENT)) x $ELEMENTS ]; 

     sleep(2); 

     if(!defined($hash{$key}->{'amplification'})){ 
      $hash{$key}->{'amplification'} = []; 
     } 

     push(@{$hash{$key}->{'amplification'}},@{$arrref1}); 
     undef($arrref1); 
     push(@{$hash{$key}->{'amplification'}},@{$arrref2}); 
     undef($arrref2); 
     push(@{$hash{$key}->{'amplification'}},@{$arrref3}); 
     undef($arrref3); 


     sleep(3); 

     delete($hash{$key}); 

     sleep(5); 
    } 
} 

sleep(10); 
+0

170메가바이트과 같을 것이다 매우 많이 없습니다. 왜 그렇게 보수적 일 필요가 있니? 임베디드 시스템입니까? – Borodin

+0

'[(rand ($ MAX_ELEMENT)) x $ ELEMENTS]'가 같은 수의 1,000,000 개의 복사본을 가진 배열을 생성한다는 것을 알고 있습니까? – Borodin

+0

방금 ​​큰 번호 (1,000_000_000')에 수천 개의 구분 기호를 추가했습니다. 이것은 Perl의 구문 당 (syntactic sugars) 중 하나입니다 : [whitin 수는 Perl에서 무시되고 가독성을 향상시킬 수 있습니다.] (http : //perldoc.perl.org/perldata.html # 스칼라 값 생성자). – PerlDuck

답변

6

펄 자주 묻는 질문을 3-How can I free an array or hash so my program shrinks?

을 당신은 일반적으로 수 없습니다. 어휘에 할당 된 메모리 (즉, my() 변수) 은 범위를 벗어나더라도 다시 회수하거나 재사용 할 수 없습니다. 변수가 범위 안으로 되돌아 오는 경우에 대비하여 예약 된 것은 입니다. 전역 변수에 을 할당 한 메모리는 undef() 및/또는 delete()를 사용하여 (프로그램 내에서) 재사용 할 수 있습니다.

대부분의 운영 체제에서는 프로그램에 할당 된 메모리를 절대로 시스템에 반환 할 수 없습니다. 그래서 장기 실행 프로그램이 때때로 다시 실행됩니다. 일부 작동하는 시스템 (특히 큰 덩어리를 할당하기 위해 mmap (2)를 사용하는 시스템)은 더 이상 사용되지 않는 메모리를 회수 할 수 있지만 시스템에서는 perl을 구성하고 OS의 malloc 인 을 사용하도록 컴파일해야합니다 펄이 아니라.

일반적으로 메모리 할당 및 할당 해제는 이 아니며 Perl에서 많이 걱정할 수도 있습니다.

도 참조 "Perl 프로그램의 메모리 사용량을 줄이려면 어떻게해야합니까?"

+0

적어도 POSIX 시스템에서는 그렇게 효율적이지 않습니다. POSIX에서'malloc'과'free'는 최상의 범용 메모리 관리를 위해 최적화되었습니다. 자신 만의 롤링은 코드 복제 또는 효율성 저하입니다. – shawnhcorey

+0

@ shawnhcorey p5p가 개선점을 논의 할 것이라고 확신합니다 –

0

일반적으로 perl은 메모리를 시스템으로 해제하지 않습니다. 다른 목적으로 필요할 경우에 대비하여 자체 메모리 풀을 유지합니다. 어휘 데이터는 루프에서 자주 사용되기 때문에 많은 일이 발생합니다. 예를 들어 $arrref1 변수는 백만 개의 요소 배열을 나타냅니다. 그 배열에 대한 메모리가 시스템에 반환되고 매회 루프 주위를 재 할당하면 엄청난 속도 벌칙이 걸릴 것입니다.

필자가 쓴 것처럼 170MB는 그리 많지는 않지만 큰 것을 버리면 발자국을 줄일 수 있습니다 임시 배열을 만들고 해시 요소에 직접 목록을 추가합니다. 당신이 불필요하게 각 배열의

를 두 복사본을 유지하는 의미로이

use strict; 
use warnings 'all'; 

sleep 30; 

use constant ELEMENTS => 1_000_000; 
use constant MAX_ELEMENT => 1_000_000_000; 

my $if_condition = 1; 

sleep 5; 

my %hash = (1 => {}, 2 => {}, 3 => {}, 4 => {}); 

foreach my $key (keys %hash) { 

    next unless $if_condition; 


    sleep 2; 

    push @{ $hash{$key}{amplification} }, (rand MAX_ELEMENT) x ELEMENTS; 
    push @{ $hash{$key}{amplification} }, (rand MAX_ELEMENT) x ELEMENTS; 
    push @{ $hash{$key}{amplification} }, (rand MAX_ELEMENT) x ELEMENTS; 


    sleep 3; 

    delete $hash{$key}; 

    sleep 5; 
} 

sleep 10; 
+0

작은 스크립트가 가능한 효율적으로 작성되지는 않았지만 의도적으로 위의 코드를 붙여 넣은 것은 좀 더 복잡한 스크립트의 단순화 된 버전이므로 (나는 여기에 붙여 넣을 수 없다). 세 개의 임시 배열은 함수의 결과이며 해당 함수의 출력은 동일하게 유지되어야합니다. – user1834095

관련 문제