in reply to BEGIN initialization and memory

Perl never reclaims used memory to your operating system during the course of your program. It keeps it allocated until the process ends. In the case of mod_perl, the Perl process runs as long as Apache runs, so you won't be able to "give back" memory to the OS. Update: I stand corrected. See BrowserUK's reply below.

However, the lexical scope of BEGIN blocks is the same as any other block, so the garbage collection will have the same effect as any other block structure. Unfortunately for you in this case, Perl's named subs are not lexically scoped, and can't be "cleaned up" as such.

You could however use anonymous subs, which can be scoped and cleaned up lexically, or you could clear out the symbol table entry for subs you declare in the BEGIN block. It's my understanding that doing either of these would trigger garbage collection for the subs. Their memory would be recliamed by Perl but not by the OS. In these cases, Perl would reuse the memory later, so it might still be a solution to your memory concerns.

blokhead

Replies are listed 'Best First'.
Re: Re: BEGIN initialization and memory
by BrowserUk (Patriarch) on Jul 23, 2003 at 07:37 UTC

    Perl never reclaims used memory to your operating system during the course of your program.

    According to the man that knows, this isn't exactly so, as he explained here.

    You can actually what this happen in Win32 if you monitor memory usage with the task manager and type the following

    P:\test>perl58 -de1 Loading DB routines from perl5db.pl version 1.19 Editor support available. Enter h or `h h' for help, or `perldoc perldebug' for more help. main::(-e:1): 1 DB<1> ;{ $s = 'X' x 30_000_000 } DB<2>

    After entering that line into the debugger, I can watch the memory for the task grow to close 100 MB, and then fall most of the way back to the 4 MB that it started out as, as $s goes out of scope and its memory is returned to the OS.

    You could probably do something similar using top under *nix.


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller

      Thanks for the info and link, BrowserUK. I believe I missed that late post to that thread. It sounds like one shouldn't (yet) rely fully on Perl freeing your unused blocks, which is why questions about freeing memory are generally answered along the lines of "don't worry about it, just write efficient algorithms, the GC will do what it can, etc.." Anyway, I probably shouldn't have said Perl never reclaims used memory, since it's quite clear Elian knows better what he's talking about than I!

      FYI, Perl frees the blocks in your sample code on my Linux system.

      blokhead

        It's fairly clear that Elian knows better than most of us. Shame we can't (yet?) do brain transfusions, we could all benefit:)

        Thanks for conforming that the demo works on Linux, I thought it should, but didn't have any way to confirm it.


        Examine what is said, not who speaks.
        "Efficiency is intelligent laziness." -David Dunham
        "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller

      one note though, in your example you are allocating one huge block, in most live programs they dont presize arrays or hashes and end up growing them with a loop. in those cases the memory will most likly never be released. So in most cases it is safe to think about the memory, once allocated, being stuck allocated to your running program.

      -Waswas

        Agreed its a clumsy demonstration. However, I have seen the memory returned in more realistic situations. For example, if you copy a large array when sorting it

        my @a = 1 .. 100000; @a = sort{ $b <=> $a } @a;

        When I run this code, I can watch the memory usage peak at around 21 MB, but then fallback to around 18 MB. So even in this fairly simple and common operation, some memory is being returned to the OS. Not all of it, as loading the array only consumes around 8 MB, so the post sort figure of 18 shows that a considerable amount of "working storage" hasn't been returned to the OS. If you then empty the array @a = ();, another 3 or 4 MB is released. Interestingly, if you then undef @a; another 1 MB or so is released. Skipping the null list assignment step takes you straight to the (same) final position.

        It would be a labour of love to try and understand what and when this occurs enough to be able to reliably make use of the information, so the your basic point about essentially ignoring it probably sage advice in most situations.


        Examine what is said, not who speaks.
        "Efficiency is intelligent laziness." -David Dunham
        "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller

Re: Re: BEGIN initialization and memory
by bsb (Priest) on Jul 23, 2003 at 07:35 UTC
    So the memory for the BEGIN code itself is released to perl's memory pools then?

    Thanks.

    I started playing with some of this.