Perl에서 동적 구조체인 문자열, 배열, 해시에 대한 메모리는 참조 카운팅(reference counting)과 내부 자동 스케일링 메커니즘을 통해 자동으로 관리됩니다. 이는 언어의 초기 버전부터 핵심 특징 중 하나가 되어 명시적인 자원 해제 없이 객체를 생성하고 삭제할 수 있게 해줍니다.
문제: 참조를 잘못 관리하거나 중첩 구조를 대량으로 생성할 경우 메모리 누수와 잦은 재배치로 인한 성능 문제를 유발할 수 있습니다.
해결책: 누수를 방지하기 위해 순환 참조를 피하고 약한 참조(모듈 Scalar::Util 사용)를 활용하며, 대량 데이터 작업 시 구조의 크기를 예측하는 것이 좋습니다(keys, scalar, map을 이용한 선제적 메모리 할당).
코드 예시:
use Scalar::Util 'weaken'; my $a = {}; my $b = { link => $a }; $a->{link} = $b; weaken($a->{link}); # 이제 순환 참조로 인한 메모리 누수가 발생하지 않음
주요 특징:
Perl은 변수가 범위를 벗어난 후 자동으로 메모리를 해제한다고 보나요?
일반적으로는 그렇지만, 순환 참조가 있으면 참조 카운트가 0보다 크기 때문에 메모리가 해제되지 않습니다.
my $a = {}; $a->{self} = $a; # 범위를 벗어난 후 $a는 weaken 없이는 해제되지 않음
Perl은 배열을 비워지거나 재할당한 후 큰 배열을 해제할 수 있나요?
항상 그렇지는 않습니다. 예를 들어, 배열을 비웁니다면 메모리가 즉시 OS에 반환되지 않고 재사용을 위해 예약될 수 있습니다.
my @big = (1..1_000_000); @big = (); # 메모리가 예약된 상태로 남아 있을 수 있음
해시/배열을 동시에 대량으로 작업하면 어떻게 되나요?
Perl은 필요에 따라 메모리를 할당하지만, 데이터 양이 많아지면 조각화 및 성능 저하가 발생할 수 있습니다.
웹 프로젝트에서 각 요청 시 객체 체인이 생성되는데, 이 중 일부는 순환 참조를 포함합니다. 시간이 지나면서 프로세스가 커지고 메모리를 지나치게 소비하게 됩니다.
장점:
단점:
프로그래머는 모든 순환 참조에 대해 weaken을 사용하고 Devel::Peek 및 Devel::Size 모듈을 통해 메모리를 프로파일링합니다.
장점:
단점: