As someone who has recently discovered the sweet creamy goodness of mod_perl, I would like to pass along some wisdom that I learned during my self-teaching crash-course. I am just another below-average Perl Hacker, so take all advice with a (large) grain of salt:

  • Use 'use strict;' - I cannot express that enough. I'll say it again; use strict;. Too many people think that it is really an optional thing and, in regular perl programs, it might be; but in the mod_perl world you have three options: 'use strict;' (thereby forcing you to declare variables with the 'my' operator to limit scope), make sure you explicitly define your variables' values before they are evaluated (i.e. "$scalar = '';") or undefine everything at the end (i.e. "undef $scalar;"). Which do you think will be easier?

    The reason here, as was already stated above, is that mod_perl keeps a compiled copy of the script in memory, along with any variable values (unless they have gone out of scope or have been undefined). However, there may be one or two times you *want* a variable to be persistent -- the first thing that comes to mind is a database handle. If it persists across multiple executes, you won't have the overhead of re-initializing the database connection every time.

  • Restart Apache when you make a change - Because a compiled copy of your script is kept in memory, if you make a change to the source, the change won't immediately be available as with traditional CGIs. To flush the compiled scripts from memory, the easiest way I've learned is to simple restart the 'httpd' daemon. And the easiest way to do this is is "/path/to/apache/bin/apachectl restart".

  • Optimize your Code - Sure, using mod-perl is fast, but it won't make up for sloppy, inefficient code. Clean things up, don't make nth-iteration loops if you don't have to.

  • Get more memory - Since a lot of stuff will get stuffed into RAM, you'll need more memory then is traditionally needed, especially if you have multiple scripts being executed concurrently. It can devour core faster than Delta Burke chows Snackwells. I thought I could get decent performance using 32 megabytes of RAM... I was so wrong.

  • Remeber that page headers can he handled for you - Output from a perl program being run though mod_perl will automagically be prefixed with the appropriate header. That means if you're like me an used to use 'print "Content-type: text/html\n\n";' to do headers, it will actulally display that line at the top of the outputted page.

    The way to overcome this is (my personal opinion) to use the perl CGI module to create your headers:

    my $query = new CGI;
    print $query->header ();

    The CGI module talks to mod_perl so if only one of the two entities involved prints the line so you don't get duplicates. Additionally, if you need a header for a differnet MIME type, use something like:

    print $query->header ('text/x-hdml');

    ...and that will cause mod_perl and Apache to send an HDML header verses an HTML header.

Additional (5/2/01): There is another nasty problemn with mod_perl that I think you all need to be aware ofef -- the neffarious 'require' problem, otherwise known long-windedly as 'my code only runs the first time, then dies!' problem.

This happens because mod_perl is trying to save time, and therefor will only process 'require' statements once (unless %INC is modifed). The problem here is that if you did not define a package in your require'd file, you will not be able to access those subs the next time it is run, and it will die with an 'unable to locate method' error in the Apache Log.

Another side of nastiness here I recently learned all about is if two require'd codeblocks possess the same package name but have different contents and are being called in two differnt programs they will still share address space anyway, and it will still only be loaded once. So when the second program tries to access methods not in the first programs' require'd codeblock, it will also die with the usual error. I've been trying some workarounds about this, and saddly the only one that seems feasable is to make sure to not have require'd packages possess the same name petween different entitites (programs).