You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl@perl.apache.org by Paul Lindner <li...@inuus.com> on 2001/10/14 01:15:41 UTC

Saving memory with BEGIN blocks?

I'm doing some research in perl's (and by extension mod_perl's) use of
memory.  I recently used the terrific B::TerseSize module to profile a
number of modules used in my server and found some discrepency in
sizes.  The total bytes used was greater than the sum of the
individual elements.

Digging deeper I found that the module in question initialized a
package variable when the module was loaded.  I moved the code into a
BEGIN block and the memory usage dropped.

I then performed a test case (see below) and verified that this is the
case.

I've not seen this mentioned as of yet, but I think it's a useful
technique to reduce the memory constraints of your mod_perl based
server.

Of course, this begs the question, why doesn't Perl free up the memory
of code placed inside modules?


Anyway, here's the proof, done on a RedHat 7.1 system with perl 5.6.0.
The module TestMem (attached) was run with and without inititialization
code in a BEGIN block.  To test I ran

perl -MTestMem -e 'TestMem::foo'

I then compared the output of the /proc/PID/statm

The results, without and with a BEGIN block are:

  305 305 261 117 0 188 44
  296 296 251 118 0 178 45

The fields here are: 

  size       total program size
  resident   size of in memory portions
  shared     number of the pages that are shared
  trs        number of pages that are 'code'
  drs        number of pages of data/stack
  lrs        number of pages of library
  dt	     number of dirty pages


So, we save about 9k just by moving code into a BEGIN block for this
simple example..



----------------------------------------------------------------------
package TestMem;

my $a = 1;
my $b = 10;

#BEGIN {
$a = $a + 10; 
$a = $a * 10; $a = $a / 9; $a = $a * 10; $a = $a / 9;
$a = $a * 10; $a = $a / 9; $a = $a * 10; $a = $a / 9;
$a = $a * 10; $a = $a / 9; $a = $a * 10; $a = $a / 9;

$b = $b * 100; $b = $b / 100; $b = $b * 100; $b = $b / 100; 
$b = $b * 100; $b = $b / 100; $b = $b * 100; $b = $b / 100;
$b = $b * 100; $b = $b / 100; $b = $b * 100; $b = $b / 100;
$b = $b * 100; $b = $b / 100; $b = $b * 100; $b = $b / 100;
$b = $b * 100; $b = $b / 100; $b = $b * 100; $b = $b / 100;
$b = $b * 100; $b = $b / 100; $b = $b * 100; $b = $b / 100;

#  }  # end begin..

sub foo {
  my $c = " " x 10000;  # hopefully reallocate freed mem...
  print "pid $$ : $a $b";
  sleep(10000000);
}
1;




-- 
Paul Lindner
lindner@inuus.com

Re: Saving memory with BEGIN blocks?

Posted by Perrin Harkins <pe...@elem.com>.
> Digging deeper I found that the module in question initialized a
> package variable when the module was loaded.  I moved the code into a
> BEGIN block and the memory usage dropped.

Looking at your test case, it seems like simply loading that module from
startup.pl would do the job.  The thing that I've seen improved by moving it
into a BEGIN is automatic accessor methods.  When I have some code that
defines accessors when they're called, I change it so that it defines them
up front in a BEGIN.  That improves sharing (assuming they are actually
used).

> Of course, this begs the question, why doesn't Perl free up the memory
> of code placed inside modules?

There's been discussion before about why Perl doesn't free memory used by
lexicals.  It does get re-used the next time the lexical is used, and you
can clear it with undef.  I think this is in the Guide, and you can find
more info in the list archives.  Doug had a good post on the subject, as I
recall.

- Perrin