http://www.perlmonks.org?node_id=470533

ISAI student has asked for the wisdom of the Perl Monks concerning the following question:

I have a general question, I will pose the scenario, and then the question: If I create an array X, I take up memory. I am to erase it (by setting it's $# to -1), and then I will create a new array, named Y, which is slightly smaller than X. Now the question: Will Perl use the memory freed from array X in order to store array Y, or allocate s different portion of memory for array Y?. basically what I am asking if there is any reason, from memory usage point of view, to use $#=-1? Thanks, -ISAI student

Replies are listed 'Best First'.
Re: memory "release" with $#=-1
by dave_the_m (Monsignor) on Jun 28, 2005 at 09:55 UTC
    $#a=-1 will free up all the elements of @a, allowing their memory to be reused. In addition, undef @a frees up the array's AvARRAY structure, which uses typically (4 x maximum array index ever used) bytes. Neither will free up the actual array itself; you need to ensure the variable goes out of scope for that.

    Dave.

      I am sorry for being obtuse. Will it improve the memory usage or not, in the same scope?
        my $a = []; $a->[$_] = $_ for 0..999; $#$a = 1; # frees up approx 16000 bytes undef @$a; # frees a further 4000 bytes undef $a; # frees a further 52 bytes
        Note that this frees memory to the perl interpter, not to the OS. ie perl can reuse that memory when creating further data, but other processes can't

        update: to clarify: just doing the undef $a on its own would free up all 20052 bytes too.

        Dave.

Re: memory "release" with $#=-1
by fmerges (Chaplain) on Jun 28, 2005 at 09:35 UTC

    Hi,

    Think you meant $#var = -1;

    Why you don't use undef?

    use warnings; use strict; my @a = (1,2,3); undef @a; print "a=",@a if @a;

    Normally you don't have two care about how Perl manages the memory. But you could use a debugger to take a look of what he is doing...

    You allways should write clean code. You can free memory manually or you can let the vars get out of scope.

    @a = (1,2,3); for my $v (@a) { print $v, "\n"; } print 'Still exist $v? '; print "No!\n" unless defined $v;

    And consider using some pragmas, like use strict and use warnings, and why not, also use diagnostics.

    Regards,

    :-)
Re: memory "release" with $#=-1
by tlm (Prior) on Jun 28, 2005 at 09:45 UTC

    I don't know if this test is conclusive, but from the result of the following script, it looks like the answer to your question is "no":

    use strict; use warnings; my @x = 1..10; print '@x is at ', \@x, "\n"; $#x = -1; my @y = 1..5; print '@y is at ', \@y, "\n"; print '@x is at ', \@x, "\n"; __END__ @x is at ARRAY(0x8165ccc) @y is at ARRAY(0x8183ab0) @x is at ARRAY(0x8165ccc)

    Update: OK, so the script above is not conclusive, as ikegami points out (in fact, as it turns out, it leads to the wrong conclusion).

    Devel::Peek is a better tool to answer this question. With the better information I must reject my earlier hypothesis: the answer is "yes" (i.e. space does get reused).

    the lowliest monk

      Your snippet doesn't prove anything. It doesn't say anything about the elements of @x and @y, just @x and @y themselves. Perl arrays are objects of sorts with pointers to structures containing the actual elements.

Re: memory "release" with $#=-1
by eXile (Priest) on Jun 28, 2005 at 16:05 UTC
    afaik, the memory that you'll free if a var is going out of scope is never released back to the OS, so perl keeps the memory allocated for future use within the script.

    In other words, the memory is free to reuse by the same perl process, but not for other processes on your system.

    I've tested this using these 3 simple scripts, and you can see doing a ps -o vsz,command | grep perl (or similar type of command, adapt to your OS, in my case it's FreeBSD), that in the first 2 cases the memory usage by the relevant perl processes is the same:

    #!/usr/bin/perl use strict; # case 1: array uses a lot of memory, and goes out of scope $0 = "highmemusage_going_out_of_scope"; { my @aap = map { $_ * $_ } ( 0 .. 100000 ); } sleep 300;
    #!/usr/bin/perl use strict; # case 2: array uses a lot of memory, and stays in scope $0 = "highmemusage_staying_in_scope"; my @aap = map { $_ * $_ } ( 0 .. 100000 ); sleep 300;
    #!/usr/bin/perl use strict; # case 3: use as baseline mem usage of your perl $0 = "reference"; sleep 300;
    Anybody more familiar with perl memory allocation please correct me if I'm wrong,