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

Is the memory used for the code/ops/(?) of a BEGIN block released after it is executed?
I'm thinking particularly of initialization code.

If so, how would you create compile time only subs?
ie. subs used during initialization which are also reclaimed.

Would this be useful to improve memory sharing under mod_perl or am I missing some other consequences?

Brad

Replies are listed 'Best First'.
Re: BEGIN initialization and memory
by blokhead (Monsignor) on Jul 23, 2003 at 06:47 UTC
    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

      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

        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
      So the memory for the BEGIN code itself is released to perl's memory pools then?

      Thanks.

      I started playing with some of this.

Re: BEGIN initialization and memory
by aquarium (Curate) on Jul 23, 2003 at 21:59 UTC
    I believe it does make sense that an initialization routine (inside BEGIN) block actually keeps the variables hanging around, otherwise you wouldn't have initialized variables, would you?

      What would you expect to happen here?

      BEGIN { my $x = 'foo'; }

      Outside of the block, would you expect to see a variable named $x? Would you expect it to have a value?

      In fact, it doesn't, because the normal lexical scoping rules apply. BEGIN isn't extra special magic in that variables leak out. It's just a normal block that happens to execute at a special time.

      Is the memory used for the code/ops/(?) of a BEGIN block released after it is executed? I'm thinking particularly of initialization code.

      I'm talking about the memory required for the compiled perl code of the BEGIN block itself.