Improving mod_perl Driven Site's Performance -- Part V: Sharing Memory Page 4
To remind you why do we look for the smallest value in the column diff, recall the real memory usage formula:
RAM_dedicated_to_mod_perl = diff * number_of_processes
+ the_processes_with_largest_shared_memory
Notice that the smaller the diff is, the bigger the number of processes you can have using the same amount of RAM. Therefore every 100K difference counts, when you multiply it by the number of processes. If we take the number from the version version (1) vs. (4) and assume that we have 256M of memory dedicated to mod_perl processes we will get the following numbers using the formula derived from the above formula:
RAM - largest_shared_size
N_of Procs = -------------------------
Diff
268435456 - 2609152
(ver 1) N = ------------------- = 309
860160
268435456 - 2469888
(ver 5) N = ------------------- = 262
1011712
So you can tell the difference (17% more child processes in the first version).
Initializing CGI.pm
CGI.pm is a big module that by default postpones the compilation of
its methods until they are actually needed, thus making it possible to
use it under a slow mod_cgi handler without adding a big
overhead. That's not what we want under mod_perl and if you use
CGI.pm you should precompile the methods that you are going to use
at the server startup in addition to preloading the module. Use the
compile method for that:
use CGI;
CGI->compile(':all');
where you should replace the tag group :all with the real tags and
group tags that you are going to use if you want to optimize the
memory usage.
I'm going to compare the shared memory foot print by using the script
which is back compatible with mod_cgi. You will see that you can
improve performance of this kind of scripts as well, but if you really
want a fast code think about porting it to use Apache::Request for
CGI interface and some other module for HTML generation.
So here is the Apache::Registry script that I'm going to use to
make the comparison:
preload_cgi_pm.pl ----------------- use strict; use CGI (); use GTop ();
my = new CGI;
print ->header('text/plain');
print join "\n", map {"sh => ".->param(sh) } ->param;
print "\n";
my = GTop->new->proc_mem(25885); my = ->size; my = ->share;
my = - ; printf "%8s %8s %8s\n", qw(Size Shared Diff); printf "%8d %8d %8d (bytes)\n",,,;
The script initializes the CGI object, sends HTTP header and then
print all the arguments and values that were passed to the script if
at all. At the end as usual I print the memory usage.
As usual I are going to use a single child process, therefore I will use this setting in httpd.conf:
MinSpareServers 1 MaxSpareServers 1 StartServers 1 MaxClients 1 MaxRequestsPerChild 100
I'm going to run memory benchmarks on three different versions of the startup.pl file. I always preload this module:
use Gtop();
- option 1
-
Leave the file unmodified.
- option 2
-
Preload
CGI.pm:use CGI ();
- option 3
-
Preload
CGI.pmand pre-compile the methods that I'm going to use in the script:use CGI (); CGI->compile(qw(header param));

