blokhead has asked for the wisdom of the Perl Monks concerning the following question:

Hello monks, I'm building a medium-sized web application which currently runs under plain-ol' CGI. I have about 10 modules that each correspond to a table in the database (using an interface similar to Class::DBI). These DB object modules are all use'd by the main module (MyApp), and this main module is use'd by the CGI script as such:
# application.pl use MyApp; MyApp->run;
Each page request takes about .5-.6 seconds to execute, which is a little much for my taste. So I wanted to try running it under mod_perl. I profiled the program, and found that MyApp::BEGIN takes up about 70% of the execution time, because it in turn loads the other dozen modules. (In fact, that's the only thing I can see that is done in BEGIN) It was my understanding that in mod_perl, the modules would be loaded once and then stay resident in memory for subsequent requests, thus saving the time taken by BEGIN. However, this didn't turn out to be the case. In fact, things were about 5-10% slower under mod_perl.

Am I missing something big here? I'm quite new to mod_perl, and perhaps there is a more optimized way to load all my modules. How should I structure my application so that the modules are memory-resident in mod_perl? It would be really nice to get request times down to around .1 or .2 seconds. Thanks in advance!

Replies are listed 'Best First'.
Re: mod_perl application structure
by Ovid (Cardinal) on Aug 23, 2002 at 22:02 UTC

    What you're describing sounds a bit odd. The modules generally do stay memory resident. What you can do is load all of the modules when Apache starts with a startup script. First, you add something similar to the following to you httpd.conf.

    PerlTaintCheck On PerlRequire /usr/local/apache/perllib/startup.pl <Directory /usr/local/apache/htdocs/mod_perl> SetHandler perl-script PerlHandler Apache::Registry PerlSendHeader On AllowOverride None Options +ExecCGI </Directory>

    Then, a typical startup.pl script:

    #!/usr/bin/perl -w use strict; use lib '/usr/local/apache/perllib'; use Apache::Registry; use CGI; CGI->compile(':all'); use CGI::Carp ''; use DBI; use DBD::Pg; 1;

    You'd want to customize the startup script to suit your needs, but that will preload your modules for you when Apache starts. If that's your bottleneck, it's gone away.

    use DBI;

    Cheers,
    Ovid

    Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

Re: mod_perl application structure
by perrin (Chancellor) on Aug 23, 2002 at 21:59 UTC
    Yes, you're missing something big. You are almost certainly not running your applications under mod_perl. Either that, or you are using up all the RAM on your machine and causing it to go into swap.

    The information you need is all here.

      I'm pretty positive it is using mod_perl -- The script now prints out Content-type: text/html at the top (haven't gone and changed the output yet). I'll check into the memory usage.
        See if $ENV{'MODPERL'} is true in your script. Also, I assume you're running under Apache::Registry, right?

        You will want to look into using Apache::DBI, and pre-loading all of your modules in a startup.pl script to save memory.

Re: mod_perl application structure
by trs80 (Priest) on Aug 23, 2002 at 22:04 UTC
    How/Where are you preloading the modules? Are you using Apache::DBI? If you are make sure it is loaded before any DBI calls including the loading of.

    Setup perl-status
    <Location /perl-status> SetHandler perl-script PerlHandler Apache::Status order deny,allow #deny from all allow from all # adjust for your IP </Location>
    and preload Apache::Status BEFORE Apache::DBI, if you haven't already. That will allow you to confirm that Apache::DBI is caching the DBI connects and you can see what modules are loaded into memory.