> >    However, I've noticed that scripts that generate lot of output take
> >    substantially longer to run than their CGI counterparts.
> > 
> >    The CGI script took 1.59 seconds to run, whereas the mod_perl version 
> >    took 3.38 seconds.  It generates about 321K of output.
> 
> Are you positive that they generated identical output?

The output isn't quite identical -- there are some differences because
of differing script names and whitespace.  But they're within a few
hundred bytes of each other.

> How were you doing this filtering in your CGI script? 

I had a written an SSI parser in Perl.  It's not exactly optimized and
is about six years old, but it basically recursed through INCLUDE 
directives until it found a script or other SSI directive to execute.
Script output was captured by doing print `script`;

> >    I'm guessing that it's because Apache::Filter loads the output of
> >    each filter into memory before passing it on. 
> 
> That's a good guess.  Why don't you profile it and find out where the
> problem is?  Try Apache::DProf.

Hey, neat.  :)  I didn't know about that.  

   Here's the output after a few loads:
   # dprofpp -F 24939/tmon.out 
   Faking 2 exit timestamp(s).
   Total Elapsed Time = -0.05622 Seconds
     User+System Time =        0 Seconds
   Exclusive Times
   %Time ExclSec CumulS #Calls sec/call Csec/c  Name
    0.00   6.359  6.347   8921   0.0007 0.0007  Apache::Filter::PRINTF
    0.00   1.163  8.016      3   0.3877 2.6719  Apache::RegistryFilter::handler
    0.00   0.410  0.397   8996   0.0000 0.0000  DBI::st::fetchrow_arrayref
    0.00   0.050  0.050     16   0.0031 0.0031  DBI::st::execute
    0.00   0.050  0.099      2   0.0250 0.0494  Apache::SSI::handler
    0.00   0.030  0.030      6   0.0050 0.0050  CGI::new
    0.00   0.030  0.030      8   0.0037 0.0037  CGI::AUTOLOAD
    0.00   0.020  0.030     65   0.0003 0.0005  Apache::PRINT
    0.00   0.020  0.030      1   0.0200 0.0298  Apache::DBI::childinit
    0.00   0.010  0.010     15   0.0007 0.0007  Apache::send_cgi_header
    0.00   0.010  0.010      6   0.0017 0.0017  CGI::Util::expires
    0.00   0.010  0.010      4   0.0025 0.0025  vars::import
    0.00   0.010  0.010     11   0.0009 0.0009  DBI::_new_dbh
    0.00   0.010  0.010     24   0.0004 0.0004  DBI::db::prepare
    0.00   0.010  0.048     12   0.0008 0.0040  Apache::Registry::handler

It looks like the problem is repeated print statements.  I basically
had a loop that did

   while ($ref = $sth->fetchrow_arrayref()) {
      print $$ref[0], $$ref[2], etc.
   }

Changing it to

   my $output;
   while ($ref = $sth->fetchrow_arrayref()) {
      $output .= $$ref[0] . $$ref[2], etc.
   }
   print $output;

cut the load time to 1.03 seconds -- that's 1/3 of the timing with multiple
print statements and 2/3 of the timing for the CGI script.

So the lesson I learned is to store all of your output when using 
Apache::Filter, then print it all out at once.

Thanks for the pointer, Perrin!

Chris

-- 
Reporting bugs: http://perl.apache.org/bugs/
Mail list info: http://perl.apache.org/maillist/modperl.html

Reply via email to