読者です 読者をやめる 読者になる 読者になる

Perlでのメモリ開放について

Perlで大規模な処理をしたときに、メモリに気を使わないといけないことがあって、メモリの開放について調べたときに、以下のページを見て、スコープ外れただけではメモリ開放されないことを知ったので、自分でも試してみた。
http://skitai.blog98.fc2.com/blog-entry-49.html


メモリ使用量の確認には Devel::MemUsed を利用。昔はcpanにあったぽいけど、今はないようなので、https://github.com/jozef/devel-memused からcloneして使う


use v5.14;
use strict;
use warnings;

use lib glob "modules/*/lib";

use Devel::MemUsed;

my $mem_used = Devel::MemUsed->new;
$mem_used->reset;
say $mem_used->used; ## 160

何もしてないと、160とでる

% perl memory_check.pl
160


以下の場合だと、2208となる

$mem_used->reset;
my $buff = 'a' x 1000;
say $mem_used->used; ## 2208

スコープ外れてもメモリ使用量かわらない

$mem_used->reset;
{
    my $buff = 'a' x 1000;
}
say $mem_used->used; ## 2208

undef すると、$buff分、メモリが減る

$mem_used->reset;
my $buff = 'a' x 1000;
undef $buff;
say $mem_used->used; ## 1184

メソッドで試す

メソッドで利用した場合も何もしなければ開放されない

$mem_used->reset;
my $buff = 'a' x 1000;
$buff = copy($buff);
say $mem_used->used; ## 4288

sub copy {
    my ($buff) = @_;
    my $res = $buff;
    $res;
}

複数回呼んでも、再利用されるのでメモリ量は同じ

$mem_used->reset;
my $buff = 'a' x 1000;
$buff = copy($buff);
$buff = copy($buff);
say $mem_used->used; ## 4288

メソッド内でundefすればメモリ開放される

$mem_used->reset;
my $buff = 'a' x 1000;
$buff = copy2($buff);
say $mem_used->used; ## 3248

sub copy2 {
    my ($buff) = @_;
    my $res = $buff;
    undef $buff;
    $res;
}

クラスで試す

メソッドと同様、クラス内のメソッドも同じ感じ。

$mem_used->reset;
my $buff = 'a' x 1000;
my $copy = Copy->new;
$buff = $copy->copy($buff);
say $mem_used->used; ## 4688


package Copy;

sub new {
    my $class = shift;
    bless {}, $class;
}

sub copy {
    my ($self, $buff) = @_;
    my $res = $buff;
    $res;
}

1;


インスタンスをundefしても、メソッドのメモリはそのまま

$mem_used->reset;
my $buff = 'a' x 1000;
my $copy = Copy->new;
$buff = $copy->copy($buff);
undef $copy;
say $mem_used->used; ## 4688


Perlでメモリについてあんまり考えたことや調べたことなかったから、よくわからないけど、メモリオーバーしそうになったら、勝手に開放してくれるんだろうか。