[Date Prev][Date Next][Thread Prev][Thread Next] [Search] [Date Index] [Thread Index]

[MacPerl] Apparent MacPerl 5 memory handling oddities



(This is a copy of a message with which I pestered poor Matthias a while
back; from his graceful silence, I infer that it would probably be better
directed to the list, in the hope that someone with more free time on their
hands can provide an answer. Particularly since I suspect that this is
related to my misunderstanding of the way Perl works/should work, rather
than an actual quirk of MacPerl).

My question is about the way MacPerl 5.1.0r2 handles memory. I have a test
script that creates an object, assigns a large number of 'instance
variables' to that object (which is realised as a simple hash reference),
then exits the subroutine in which the object was created, destroying it.

The first time I run the script, assignment of the instance variables takes
a large chunk of memory (using 'FreeMem' to monitor memory). When the
object is destroyed, much of this memory is not recovered. If I re-run the
script (without restarting MacPerl) subsequent assignments (to a new
object) take very much less memory, and almost all of it is subsequently
recovered.

Have I failed to understand something fundamental, or is there something
strange going on? Is this a quirk of MacPerl, or does Perl always behave
like this?

        Many thanks,

                        A

----------------------------- script follows -----------------------------

#!/usr/bin/perl


use Mac::Memory;

print STDERR "On startup: ", &FreeMem(), "\n";
&test();
print STDERR "On fn exit: ", &FreeMem(), "\n";

# test
#
# Thrash MacPerl hard by making it assign lots of items to a hash.

sub test {
        print STDERR "Before creation: ", &FreeMem(), "\n";
        my($foo) = new Foo;
        print STDERR "After creation: ", &FreeMem(), "\n";

        # Assign a large number of values to the hash. The 'sqrt'
        # nonsense is simply to make the hashing algorithm sweat
        # a little.

        my($index,$key);
        for($index=0;$index<10000;$index++) {
                $key = sqrt($index*2);
                $foo->{$key} = $index;
        }
        print STDERR "After allocating first batch: ", &FreeMem(), "\n";

        # Do it again for another batch of items

        for($index=10000;$index<20000;$index++) {
                $key = sqrt($index*2);
                $foo->{$key} = $index;
        }
        print STDERR "After allocating second batch: ", &FreeMem(), "\n";

        # And a third time

        for($index=20000;$index<30000;$index++) {
                $key = sqrt($index*2);
                $foo->{$key} = $index;
        }

        # Let the user know how much memory we've used up.

        print STDERR "After allocating third batch: ", &FreeMem(), "\n";
}


# ---------------------------------------------------------------------------
#
# ---------------------------------------------------------------------------

package Foo;

sub new {
        my($type) = shift;
        bless {}, $type;
}

sub DESTROY {
        my($self) = shift;
        warn "DESTROYed $self";
}

------------------------------- script ends -----------------------------

--
         angus@pobox.com                   http://pobox.com/~angus

   "I like lobsters better than people. They are calm, silent, and
    they know the secrets of the deep." [Gerard de Nerval (attrib)]