Improving mod_perl Driven Site's Performance -- Part IV: Sharing Memory Page 3
So imagine that you have this 10Mb in-memory database that resides in
a single variable, you perform various operations on it and want to
make sure that the variable is still shared. For example if you do
some matching regular expression (regex) processing on this variable
and want to use the pos() function, will it make the variable unshared
or not?
The Apache::Peek module comes to rescue. Let's write a module
called MyShared.pm which we preload at server startup, so all the
variables of this module are initially shared by all children.
MyShared.pm --------- package MyShared; use Apache::Peek;my = "Chris";sub match { =~ /\w/g; } sub print_pos{ print "pos: ",pos(),"\n";} sub dump { Dump(); } 1;This module declares the package
MyShared, loads theApache::Peekmodule and defines the lexically scopedvariable which is supposed to be a variable of large size (think about a huge hash data structure), but we will use a small one to simplify this example.The module also defines three subroutines:
match()that does a simple character matching,print_pos()that prints the current position of the matching engine inside the string that was last matched and finally thedump()subroutine that calls theApache::Peekmodule'sDump()function to dump a raw Perl data-type of thevariable.Here is the script that prints the process ID (PID) and calls all three functions. The goal is to check whether
pos()makes the variable dirty and therefore unshared.share_test.pl ------------- use MyShared; print "Content-type: text/plain\r\n\r\n"; print "PID: 20986\n"; MyShared::match(); MyShared::print_pos(); MyShared::dump();Before you restart the server, in httpd.conf set:
MaxClients 2for easier tracking. You need at least two servers to compare the print outs of the test program. Having more than two can make the comparison process harder.
Now open two browser windows and issue the request for this script several times in both windows, so you get different processes PIDs reported in the two windows and each process has processed a different number of requests to the share_test.pl script.
In the first window you will see something like:
PID: 27040 pos: 1 SV = PVMG(0x853db20) at 0x8250e8c REFCNT = 3 FLAGS = (PADBUSY,PADMY,SMG,POK,pPOK) IV = 0 NV = 0 PV = 0x8271af0 "Chris"\0 CUR = 5 LEN = 6 MAGIC = 0x853dd80 MG_VIRTUAL = &vtbl_mglob MG_TYPE = 'g' MG_LEN = 1And in the second window:
PID: 27041 pos: 2 SV = PVMG(0x853db20) at 0x8250e8c REFCNT = 3 FLAGS = (PADBUSY,PADMY,SMG,POK,pPOK) IV = 0 NV = 0 PV = 0x8271af0 "Chris"\0 CUR = 5 LEN = 6 MAGIC = 0x853dd80 MG_VIRTUAL = &vtbl_mglob MG_TYPE = 'g' MG_LEN = 2We see that all the addresses of the supposedly big structure are the same (
0x8250e8cand0x8271af0), therefore the variable data structure is almost completely shared. The only difference is inSV.MAGIC.MG_LENrecord, which is not shared.So given that the
variable is a big one, its value is still shared between the processes, while part of the variable data structure is non-shared. But it's almost insignificant because it takes a very little memory space.
