Improving mod_perl Sites' Performance: Part 4
by Stas Bekman
|
Pages: 1, 2, 3, 4, 5
So given that the $readonly 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.
Now if you need to compare more than variable, doing it by hand can be
quite time consuming and error prune. Therefore it's better to
correct the testing script to dump the Perl data-types into files (e.g
/tmp/dump.$$, where $$ is the PID of the process) and then using
diff(1) utility to see whether there is some difference.
So correcting the dump() function to write the info to the file will
do the job. Notice that I use Devel::Peek and not
Apache::Peek. The both are almost the same, but Apache::Peek
prints it output directly to the opened socket so I cannot intercept
and redirect the result to the file. Since Devel::Peek dumps
results to the STDERR stream I can use the old trick of saving away
the default STDERR handler, and open a new filehandler using the
STDERR. In our example when Devel::Peek now prints to STDERR it
actually prints to our file. When I'm done, I make sure to restore the
original STDERR filehandler.
So this is the resulting code:
MyShared2.pm
---------
package MyShared2;
use Devel::Peek;
my $readonly = "Chris";
sub match { $readonly =~ /\w/g; }
sub print_pos{ print "pos: ",pos($readonly),"\n";}
sub dump{
my $dump_file = "/tmp/dump.$$";
print "Dumping the data into $dump_file\n";
open OLDERR, ">&STDERR";
open STDERR, ">".$dump_file or die "Can't open $dump_file: $!";
Dump($readonly);
close STDERR ;
open STDERR, ">&OLDERR";
}
1;
When if I modify the code to use the modified module:
share_test2.pl
-------------
use MyShared2;
print "Content-type: text/plain\r\n\r\n";
print "PID: $$\n";
MyShared2::match();
MyShared2::print_pos();
MyShared2::dump();
And run it as before (with MaxClients 2), two dump files will be created in the directory /tmp. In our test these were created as /tmp/dump.1224 and /tmp/dump.1225. When I run diff(1):
% diff /tmp/dump.1224 /tmp/dump.1225
12c12
< MG_LEN = 1
---
> MG_LEN = 2
We see that the two padlists (of the variable readonly) are
different, as we have observed before when I did a manual comparison.
In fact we if we think about these results again, we get to a
conclusion that there is no need for two processes to find out whether
the variable gets modified (and therefore unshared). It's enough to
check the datastructure before the script was executed and after that.
You can modify the MyShared2 module to dump the padlists into a
different file after each invocation and than to run the diff(1) on
the two files.
If you want to watch whether some lexically scoped (with my())
variables in your Apache::Registry script inside the same process
get changed between invocations you can use the
Apache::RegistryLexInfo module instead. Since it does exactly
this: it makes a snapshot of the padlist before and after the code
execution and shows the difference between the two. This specific
module was written to work with Apache::Registry scripts so it
won't work for loaded modules. Use the technique I have described
above for any type of variables in modules and scripts.
Surely another way of ensuring that a scalar is readonly and therefore
sharable is to either use the constant pragma or readonly
pragma. But then you won't be able to make calls that alter the
variable even a little, like in the example that I've just showen,
because it will be a true constant variable and you will get compile
time error if you try this:
MyConstant.pm
-------------
package MyConstant;
use constant readonly => "Chris";
sub match { readonly =~ /\w/g; }
sub print_pos{ print "pos: ",pos(readonly),"\n";}
1;
% perl -c MyConstant.pm
Can't modify constant item in match position at MyConstant.pm line
5, near "readonly)"
MyConstant.pm had compilation errors.
However this code is just right:
MyConstant1.pm
-------------
package MyConstant1;
use constant readonly => "Chris";
sub match { readonly =~ /\w/g; }
1;

