|
|
 |
Improving Performance with mod_perl
With the preceding discussion in mind, let's look at an example startup file. Suppose you want to give your scripts access to Perl library files in the /usr/local/apache/lib/perl and /var/lib/perl directories without having to put use lib statements for those directories in every single script. Suppose also that most of your scripts use the CGI.pm and DBI modules, so you want to preload them. You can accomplish these goals by writing your startup file as follows:
use strict;
use lib qw(/usr/local/apache/lib/perl);
use lib qw(/var/lib/perl);
use CGI ();
CGI->compile (':all');
use DBI ();
use DBD::mysql ();
1; # return true
Here are some things to note about this startup file, because they aren't particularly obvious:
You might not actually need to include the use lib line for the lib/perl directory. Recent versions of mod_perl search that directory automatically.
The () after the names of the modules that are preloaded prevents method names from being imported. This saves a little memory during Apache startup, and importing the names can wait until your scripts execute.
The call to CGI->compile() forces preloading of the CGI.pm methods that otherwise are autoloaded on demand. Without this call, these methods won't be loaded until later, and the code will go into the unshared address space of individual httpd children.
Normally DBI locates and loads the DBD::mysql driver when you're using the DBI module to access MySQL. But that doesn't happen until later, when you actually attempt to connect to the MySQL server. To get the advantage of preloading for the driver and not just the main DBI module, you have to load the driver explicitly at startup time.
The final line is required; don't leave it out. When Perl reads the startup file, it expects a return value of true or false to indicate whether the file executed successfully. The final line evaluates to 1 (true), which becomes the return value. If you omit the line, Apache startup fails after writing a line like this to the error log:
[error] conf/startup.pl did not return a true value
You must restart Apache each time you modify the startup file, just as when you modify httpd.conf. However, there's a slight complication in that the startup file won't be read under certain circumstances. If mod_perl is loaded as a DSO, it's torn down completely and reloaded from scratch whenever Apache restarts. In this case, you don't have anything to worry about; the startup file will be reread when mod_perl is reinitialized. On the other hand, if mod_perl is compiled in to httpd, Apache doesn't reread the startup file by default. You have a couple of options here. First, you can restart with apachectl stop followed by apachectl start. That brings the server all the way down and starts a new one, causing the entire initialization sequence to be performed. Alternatively, you can add the following directive to httpd.conf:
PerlFreshRestart on
PerlFreshRestart on explicitly tells Apache to reread the mod_perl startup file when it restarts, even for apachectl restart and apachectl graceful. However, the mod_perl Guide cautions that PerlFreshRestart can cause problems on some systems. Before deciding whether to use it, read the section in the Guide titled "Evil Things Might Happen When Using PerlFreshRestart." If you decide against it, you'll need to go the route of using apachectl stop and apachectl start to restart the server after startup file changes.
After restarting Apache, you can check whether it reloaded the startup file by requesting the perl-status page described in the section "Test Your mod_perl Configuration." If you change the Perl search path, for example, this should be reflected in the value of the @INC array at the bottom of the perl-status "Loaded Modules" page.
Alternatives to the Startup File
Some of the work that you do in the mod_perl startup file can be accomplished directly in httpd.conf. You can add directories to Perl's search path using a PerlSetEnv directive in httpd.conf to set the PERL5LIB variable. The value can be a single directory pathname or a list of colon-separated path names:
PerlSetEnv PERL5LIB /usr/local/apache/lib/perl:/var/lib/perl
However, this is less efficient than using the startup file because it adds a little overhead for each script run by mod_perl. When you set the path in the startup file, it's done once and affects all scripts automatically.
You can preload Perl modules using the PerlModule directive. This is equivalent to loading the modules in the startup file. One or more modules can be named:
PerlModule CGI DBI DBD::mysql
|