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

I'm running into a problem where my code is not the bottleneck but the modules I "use" is.

How do I benchmark modules? I tried this:

#!perl -w use Benchmark; my $bench1 = new Benchmark; use strict; use CGI ':standard'; #use XML::Simple; use HTML::Entities; use LWP::UserAgent; use LWP::Simple 'get'; use HTTP::Cookies; use HTTP::Request::Common; my $bench2 = new Benchmark; print timestr timediff $bench2, $bench1;

... but it doesn't work (keeps printing 0s). Am I doing something wrong here? Or does perl load the modules even before my code gets interpreted?
I _know_ this is the bottleneck because running this script takes ~0.3s on my ActiveState/Win2K box and the entire script doesn't take much more than that. (and no, I'm not using an extremely slow hard drive ;-) )

Seriously, I'd like to know which one of these modules is the slowest so I can find a way around it ...

Thanks,
CBAS

Replies are listed 'Best First'.
Re: Benchmarking modules
by MeowChow (Vicar) on Mar 25, 2001 at 14:44 UTC
    As you suspected, this outputs 0 because Perl executes the use command during compile-time (similar to BEGIN and END blocks). Consider using mod_perl for Apache, or PerlEx for IIS, or another similar tool to keep your Perl interpreter and its modules persistent between CGI invocations.
       MeowChow                                   
                   s aamecha.s a..a\u$&owag.print
Re: Benchmarking modules
by repson (Chaplain) on Mar 25, 2001 at 15:46 UTC
    What you are trying to benchmark is loading time, so keep that in mind. I can think of two ways to benchmark achive that aim.

    The first is timing with some tool the times (under unix use times, otherwise use Benchmark to time the system("..."); function from perl). Use the command lines:

    perl -e "" perl -e "use CGI ':standard';" perl -e "use HTML::Entities"

    Otherwise the data you want may be attainable through Devel::DProf, which is useful for seeing all bottlenecks, in compile or runtime.

Re: Benchmarking modules
by Anonymous Monk on Mar 25, 2001 at 14:36 UTC
    BEGIN { use Benchmark; use vars qw($bench1); $bench1 = new Benchmark; }
Re: Benchmarking modules
by epoptai (Curate) on Mar 26, 2001 at 14:50 UTC
    I don't know how accurate this is or exactly what it's measuring but the results suggest something useful is happening.
    #!perl use Benchmark; $count = shift || die "Need a count!\n"; sub one { eval("use CGI;")} sub two { eval("use CGI ':cgi';")} sub three { eval("use CGI ':all';")} timethese ( $count,{ 'Method 1' => '&one', 'Method 2' => '&two', 'Method 3' => '&three', } ); exit;
    Results:

    Benchmark: timing 500 iterations of Method 0, Method 1, Method 2, Method 3...

    Method 1: 0 wallclock secs (0.33 usr + 0.00 sys = 0.33 CPU) @ 1515.15/s (n=500)
    Method 2: 2 wallclock secs (1.87 usr + 0.00 sys = 1.87 CPU) @ 267.38/s (n=500)
    Method 3: 6 wallclock secs (5.55 usr + 0.00 sys = 5.55 CPU) @ 90.09/s (n=500)

    Reference: Benchmarking Your Code.

      use first does a require and then import at compile time. Through an eval you are making that a run-time affair to benchmark. Once the file has been loaded then require is essentially free. Therefore you are actually benchmarking how fast import is.

      That timing is more important for mod_perl using Apache::Registry than it is for CGI.