[첫화면으로]Perl/Perlfaq3-16

마지막으로 [b]

1. 메모리 사용량을 줄이는 방법 (How can I make my Perl program take less memory?)

원문: http://faq.perl.org/perlfaq3.html#How_can_I_make_my_Pe1


시간과 공간 중에 선택해야 하는 경우에, Perl은 거의 항상 문제를 해결하는데 공간을 사용하는 편이다. Perl의 스칼라는 C의 스트링보다 메모리를 더 사용한다. 배열은 그보다도 더 많이 사용하고, 해쉬는 더욱 많이 사용한다. 할 일이 많이 남아 있긴 하지만, 최근 배포본들에서는 이 문제를 해결하려 노력하고 있다. For example, as of 5.004, duplicate hash keys are shared amongst all hashes using them, so require no reallocation.

어떤 경우는, substr()이나 vec()을 사용하여 배열의 흉내를 내는 것이 매우 효과적이다. 예를 들어서, 천 개의 부울린 값의 배열은 최소 20,000바이트의 공간을 차지하지만, 이것을 125바이트의 비트 벡터로 변환할 수 있고, 메모리를 상당히 절약할 수 있다. 표준 모듈인 Tie::SubstrHash를 사용하면 특정한 타입의 자료 구조를 다루는 데 도움이 된다. 전문적인 자료 구조(행렬이라든지)를 다룬다면 C로 작성된 모듈이 동일한 일을 하는 Perl 모듈보다 메모리를 덜 사용할 수 있다.

당신이 사용하는 Perl이 시스템의 malloc을 사용하게 컴파일되었는지 Perl의 내장 malloc을 사용하게 되었는지 알아보라. 어느 쪽이든 간에, 다른 쪽을 사용해서 차이가 발생하는지 살펴보라. malloc에 대한 정보는 소스 배포본에 있는 INSTALL 파일에 있다. "perl -V:usemalloc"을 입력하여 당신이 perl의 malloc을 사용하고 있는지 확인할 수 있다.

물론, 메모리를 절약하기 위한 가장 좋은 방법은 첫째로 메모리를 낭비하는 일을 하지 않는 것이다. 좋은 프로그래밍 습관을 들이면 효과적일 수 있다.

파일을 라인 단위로 처리할 수 있는 경우라면 전체 파일을 한번에 메모리로 읽어들이지 말라. 더 구체적으로 말하면, 다음과 같이 루프를 사용하라:
        #
        # 좋은 방법
        #
        while (<FILE>) {
           # ...
        }
아래와 같이 하지 말라:
        #
        # 나쁜 방법
        #
        @data = <FILE>;
        foreach (@data) {
            # ...
        }
파일이 작을 때는 어떻게 하든 큰 상관 없겠지만, 파일이 커지면 큰 차이가 난다.

map과 grep은 LIST 인자를 받기 때문에, 아래와 같이 하면 전체 파일을 한번에 읽게 된다.
        @wanted = grep {/pattern/} <FILE>;

파일이 크다면 루프를 돌리는 게 낫다:
        while (<FILE>) {
                push(@wanted, $_) if /pattern/;
        }

꼭 필요한 경우가 아니라면 긴 스트링을 인용부호 안에 넣지 말라:
        my $copy = "$large_string";
위 코드는 $large_string의 사본을 두 개 만든다. ($copy의 값으로 하나, 인용하면서 하나), 반면에
        my $copy = $large_string;
이것은 사본을 하나만 만든다.

크기가 큰 배열을 다룰 때도 마찬가지이다:
        {
                local $, = "\n";
                print @big_array;
        }
위의 코드가 아래의 두 코드보다 훨씬 효율적이다.
        print join "\n", @big_array;

        {
                local $" = "\n";
                print "@big_array";
        }

배열과 해쉬를 인자로 넘길 때는 값에 의한 호출보다 참조에 의한 호출을 사용하라. 한 가지 이유는, 여러 개의 리스트나 해쉬(또는 두 종류 다)를 한 번의 호출/반환으로 넘기는 유일한 방법이기 때문이다. 또한 참조에 의한 호출을 사용하면 전체 내용의 사본을 만들지 않아도 된다. 그러나 참조에 의한 호출의 경우 인자를 변경할 경우 원래의 데이타에도 변경이 전파되므로 잘 판단해야 한다. 반드시 사본을 수정해야 한다면 사본을 저장할 메모리를 희생해야 할 것이다.

"카다란" 데이타(즉 가용 메모리를 초과할 정도의)를 보관해야 할 경우 DB 모듈을 사용하여 램 대신 디스크에 보관하는 것을 고려해보라. 이 경우 접근 시간에 손해를 보겠지만, 하드 디스크가 대량의 스와핑 작업을 하느라 버벅대게 되는 것보다는 나을 것이다.

[Tips for keeping Perl memory usage low - Stack Overflow]
-- Raymundo 2012-3-17 2:08 pm

[Memory-map files instead of slurping them | The Effective Perler]
-- Raymundo 2012-3-17 2:09 pm
이름:  
Homepage:
내용:
 


컴퓨터분류 Perl /Perlfaq

마지막 편집일: 2012-3-17 2:09 pm (변경사항 [d])
1163 hits | Permalink | 변경내역 보기 [h] | 페이지 소스 보기