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

Dear Monks,
How can I relase the entire memory of hash of hashes?
I guess it's not enough to just write %hash = (), because %hash values are pointers (refs) to other hashes which also need to be released.

Replies are listed 'Best First'.
Re: Release memory in hash of hashes
by moritz (Cardinal) on Aug 17, 2009 at 15:13 UTC
    If there are no other pointers to the values of %hash, then perl frees them. Depending on the operation system it might not hand them back to the OS though, it just reuses it for other data structures if needed.
      I don't understand exactly what you mean.
      Let's say I have
      %hash{A}{B}{C}
      I thought there should be some procedure which goes starting from %hash and releases all As, Bs and Cs
        Perl does that for you, if you empty %hash all other items are freed automagically.
Re: Release memory in hash of hashes
by BioLion (Curate) on Aug 17, 2009 at 15:22 UTC

    You can

    undef %hash;
    which will reduce it's reference count by one, and *potentially* free it's memory, provided there are no other references to the structure, or parts of it, that are still in scope.

    If you are holding any other pointers to %hash or parts of it, you'll need to undef them too (provided they are still in scope but no longer useful).

    Useful discussion here: Perl garbage collector and swap and there was a recent thread on memory de-allocation here : Memory reusability and the google book link to the internals discussion in Advanced Perl Programming.

    Although, the beauty of Perl is that you shouldn't have to worry about these sort of things! HTH

    Update: Added google book link

    Just a something something...

      You can undef %hash which will reduce it's reference count by one

      If "it" refers to the hash %hash, you're wrong.

      • %hash = (); empties the buckets, reducing the reference counts of all elements by one.

      • undef %hash; empties and frees the buckets, reducing the reference counts of all elements by one.

      However, neither lowers the reference count of %hash. (They could lower the reference count indirectly if you had something like $hash{ele} = \%hash;, but that's not what you said.)

      The later is usually overkill.

        That is what i took the OP to mean. I assumed they would never use the %hash again and wanted to totally flush it and the buckets, not just empty it. Overkill maybe...

        Just a something something...
Re: Release memory in hash of hashes
by ssandv (Hermit) on Aug 17, 2009 at 15:22 UTC

    In all likelihood, if your data is of a size where you need to be worried about freeing the memory, you'd be better off to investigate other ways of storing it, such as a database, that don't require it to all be in memory at once. Maybe if you explain the reason you are worried about memory consumption to us, we could understand what you're trying to do better and perhaps suggest a better alternative.

    Getting away from trying to micromanage memory allocation is one of the principal advantages of modern scripting languages--why exactly are you trying to out-think the compiler?

      What I am doing is I use Storable and perform
      my $word_index_ref = retrieve( $word_index_file );
      which allocates a hash of hashes of hashes (or arrays) structure.
      At some point I call a function inside this scope which needs memory and I want to release all retrieve() has poped up.

        Then assuming nothing else is referencing parts of the data structure held on to by $word_index_ref, all you need do is:

        $word_index_ref = undef;

        at which point perl will release all the memory allocated to $word_index_ref back to its heap where the memory will be available for reuse. However, do not expect to see the memory footprint for the running Perl application reduce at that point because perl typically does not hand the freed memory back to the OS.


        True laziness is hard work

        You can let scope do this for you:

        { my $word_index_ref = retrieve( $word_index_file ); # Use $word_index_ref here } # $word_index_ref is out of scope here

        When the block (scope) in which lexical variable $word_index_ref is declared is exited, the variable goes out of scope and, if there are no remaining references, associated memory is freed. This is one reason for using lexical variables and declaring them in the smallest possible scope. Sometimes an appropriate scope already exists (e.g. the blocks of subroutines, loops and conditionals), but you can create one anywhere.